News:

Let's find out together what makes a PIC Tick!

Main Menu

16 Bit H and non H registers compiler behavior.

Started by diebobo, Oct 17, 2021, 09:48 AM

Previous topic - Next topic

diebobo

Hi,

Not sure about it but here we go.. I am trying to get UART working on a 33CK256MP205 device, transmit works but receiving and using Interupt just seems to be impossible. I Think i am doing al the correct things so in a despirate attempt i looked at the created .ASM file and i think that something is going wrong there..

My .Bas looks like
U1MODEbits_UTXEN = 1; //transmitter enabled
U1MODEbits_URXEN = 1; //receiver enabled
U1MODEbits_UARTEN = 1; //enable uart

The generated .ASM part looks like :

; rd_i000024_f001_000054_p000016,0 mkr$ in [test_uart.bas] U1MODE.5 = 1
    bset.b U1MODE,#5
; rd_i000025_f001_000055_p000016,0 mkr$ in [test_uart.bas] U1MODE.4 = 1
    bset.b U1MODE,#4
; rd_i000026_f001_000056_p000016,0 mkr$ in [test_uart.bas] U1MODE.15 = 1
    bset.b U1MODEH,#7

The line of interrest is bset.b U1MODEH,#7 which should set bit 15 of the U1MODE register.

So far so good i think, butttttt if look at the declares at the top of the .ASM i find this :

.equ U1MODE, 0x0238
.equ U1MODEH, 0x0239
.equ U1MODEH, 0x023a
.equ U1MODEHH, 0x023b

I guess it works like this, the 2nd line means highbyte part of register U1MODE since its 16 bits long ? The problem i think is that there is actually a register called U1MODEH, so the reference to the Highbyte of U1MODE gets overriden with the register that has the name ( 3th line ) So values which should be written to the HighByte of U1MODE in reality gets written to the Lowbyte of the register of the samen name ?

There are however a LOT of registers that also have their names ending with a H and so far as i can see they are all affected.. Please correct me of i am wrong Les.

Using the latest version of the Compiler.

Adding my test bas file for completeness.

Device = 33CK256MP205
Declare Xtal = 100

Config FSEC     = BWRP_OFF, BSS_DISABLED, BSEN_OFF, GWRP_OFF, GSS_DISABLED, CWRP_OFF, CSS_DISABLED, AIVTDIS_OFF
Config FOSCSEL  = FNOSC_FRC, IESO_OFF
Config FOSC     = POSCMD_NONE, OSCIOFNC_ON, FCKSM_CSECMD, PLLKEN_ON, XTCFG_G0, XTBST_ENABLE
Config FWDT     = SWDTPS_PS2147483648, RCLKSEL_LPRC
Config FPOR     = BISTDIS_DISABLED
Config FICD     = ICS_PGD1, JTAGEN_OFF, NOBTSWP_DISABLED
Config FDMT     = DMTDIS_OFF
Config FDEVOPT  = ALTI2C1_OFF, ALTI2C2_OFF, ALTI2C3_OFF, SMBEN_STANDARD, SPI2PIN_PPS
Config FALTREG  = CTXT1_OFF, CTXT2_OFF, CTXT3_OFF, CTXT4_OFF
Config FBOOT    = BTMODE_SINGLE

Declare Hserial1_Baud = 9600

Dim Int_Serial_String   As String * 50 ' Hier word de complete seriele RX in opgeslagen
Dim Int_Serial_Char     As Byte

Clear

GoTo Setup ' Jump over the interrupt handlers

Setup:
'         5432109876543210
Ansela = %0000000000000000
TRISA  = %1111111111111111 ' A3/A4 = Button 1 & 2
AnselB = %0000000000000000
TRISB  = %1000001011111111
Anselc = %0000000000000000
TRISc  = %1111111111111110
Anseld = %0000000000000000
TRISd  = %1111111111111111 'D3 = Button 1

' NOOIT GEEN BITS GEBRUIKEN.. WAARDE VAN 0 of 1 DEFINEREN ALS BYTE, DAN MAAR MEER GEHEUGEN GEBRUIK... BITS WERKEN NOOIT 100%, DAGEN VERSPILD MET UITZOEKEN !!!
'              9876543210
'CNPUA = %0000000000011000  ' Interne pullups Button 2 & 3'
'CNPUd = %0010000000000000  ' Interne pullups Button 1


Osc_190MHz()                                ' Set the device to run at 190MHz

PPS_Unlock()                                ' \
PPS_Output(cOut_Pin_RP46, cOut_Fn_U1TX)    ' / Set the USART1 PPS pin
PPS_input(cIn_Pin_RP47, cIn_Fn_U1RX)    ' / Set the USART1 PPS pin

IPC2.12 = 1 ' Prio 5.. 7 is t hoogst
IPC2.13 = 0
IPC2.14 = 1

IFS0bits_U1RXIF = 0;
IEC0bits_U1RXIE = 1;   _U1RXInterrupt Enable

U1MODEbits_UTXEN = 1; //transmitter enabled
U1MODEbits_URXEN = 1; //receiver enabled
U1MODEbits_UARTEN = 1; //enable uart

DelayMS 500


clear U1STA
clear U1STAh

Main:

StrN Int_Serial_String = ""
Repeat
    HSerIn 1000, Timeout_B, [Int_Serial_Char]
    Int_Serial_String = Int_Serial_String + Int_Serial_Char
Until Int_Serial_Char = 10 Or Int_Serial_Char = 13     ' Linefeed or Cariage Return

Timeout_B:
HSerOut [Int_Serial_String, 10]

hserout ["IFS0bits_T1IF   ", dec IFS0bits_T1IF,10]
hserout ["IFS0bits_U1RXIF ", dec IFS0bits_U1RXIF,10]
hserout ["GIE             ", dec intcon2.15,10]
HSerOut ["*** U1MODE ***  5432109876543210",10]
HSerOut ["*** U1MODE ***  ", bin16 u1mode, 10]
HSerOut ["*** U1MODEH *** 5432109876543210",10]
HSerOut ["*** U1MODEH *** ", bin16 U1MODEH, 10]
HSerOut ["*** U1STA ***   5432109876543210",10]
HSerOut ["*** U1STA ***   ", bin16 U1STA, 10]
HSerOut ["*** U1STAH ***  5432109876543210",10]
HSerOut ["*** U1STAH ***  ", bin16 U1STAH, 10]


GoTo Main

end

Proc Osc_190MHz()
    ' Dit is 180 mhz
    '    CLKDIV = $3001          ' FRCDIV FRC/1, PLLPRE 1, DOZE 1:8
    '    PLLFBD = 90
    '    OSCTUN = $00
    '    PLLDIV = $21            ' POST1DIV 1:2, VCODIV FVCO/4, POST2DIV 1:1
    '    ACLKCON1 = $0101        ' FRCSEL FRC, APLLPRE 1:1
    '    APLLFBD1 = $C8
    '    APLLDIV1 = $42          ' APOST1DIV 1:4, APOST2DIV 1:2, AVCODIV FVCO/4*)

    CLKDIV = 0x3001; Dit is 100mhz
    PLLFBD = 0x96;
    OSCTUN = 0x00;
    PLLDIV = 0x32;
    ACLKCON1 = 0x8101;
    APLLFBD1 = 0x7D;
    APLLDIV1 = 0x21;
    CANCLKCON = 0x00;
    REFOCONL = 0x00;
    REFOCONH = 0x00;
    RPCON = 0x00;
    PMDCON = 0x00;
    PMD1 = 0x00;
    PMD2 = 0x00;
    PMD3 = 0x00;
    PMD4 = 0x00;
    PMD6 = 0x00;
    PMD7 = 0x00;
    PMD8 = 0x00;

    Write_OSCCONH($01)
    Write_OSCCONL($01)

    While OSCCONbits_OSWEN <> 0 : Wend  ' Wait for the clock switch to occur
EndProc

Isr U1RXInterrupt

    IFS0bits_U1RXIF = 0 ' Als m hier niet reset, en er komt een nieuwe binnen terwijl de routine nog niet klaar is pakt ie de interrupt niet.. Baluh !

    HSerOut ["*** Serieel ontvangen ", 10]

    IFS0bits_U1RXIF = 0    ' hier nog een keer resetten omdat er gewoon is blijven ontvangen door de uart terwijl we m bovenaan alweer gerest hadden... Dan keert het programma weer terug naar interupt en dan is er niets meer te ontvangen = timeout..

EndIsr

top204

#1
U1MODEH,#7 is exactly the same as U1MODE,#15, because U1MODEH is the high byte of the SFR "U1MODE", and bit-15 of a 16-bit variable is the same as bit-7 of its high byte.

In order to keep the compiler as flexible, and code efficient, as possible, it uses 8-bit mechanisms as much as it can, because not all variables and SFRs are 16-bits wide, and the compiler always splits larger variables and SFRs into 8-bit types as well, so it can seperate them in RAM.

With the 16-bit devices, the address of a variable type larger than 8-bits must always sit on an even address, and most mnemonics will give an exception if used in 16-bit mode on an address that is not sitting on an even address! So the compiler splits them so it can be more flexible and efficient where possible, but will use 16-bit mnemonics where it is thought safe to do so.

I'll check out the dsPIC33CK types again, but my initial tests showed no problems with them. They use the same mechanisms as the original dsPIC33 devices, but run faster! When using the compiler's built in hardware serial commands, do not alter the SFRs as well. The compiler alters the relevant SFRs for the Baud Rate and TX/RX, and altering the SFRs separately will cause problems if not altered correctly, because the compiler assumes default operation with the relevant SFRs. The HSerial type Declares are what setup up the compiler's internal operations.

diebobo

I think i completely understand what you are saying. Just to be sure, cause i do really have a hard time believe the following :

The following code bset.b U1MODEH,#7 is intended to set bit 15 of register U1MODE which starts at address 0x0238.

As u can see in my code snippet above, U1MODEH = declared 2 times. 1 time as 0x0239 for the highbyte part for register 0x0238 and one time as 0x023a as the lowbyte of the 16 bit register with the name U1MODEH.

So my question is, if the code bset.b U1MODEH,#7 is compiled, how does the compiler knows to use register 0x239 and not 0x023a which is declared last with the same name ?

top204

Many thanks for spotting this difference in the dsPIC33CK devices.

Microchip have, again, changed the names of the SFRs within some of the dsPIC33CK devices, so they are now removing the "L" from the end of the SFR names, so when the compiler creates the high byte of the 16-bit SFR, it is already there. The Asm30 assembler should have given an error for this because there are two .equ directives with the same name but different values following them?

I'll get into the Positron16 compiler and make the changes required so that the high byte that the compiler creates is different to the one existing in the directives.

You can try this within the .ppi file:

U1MODE EQU 0x238
U1MODEHH EQU 0x23A
U1STA EQU 0x23C
U1STAHH EQU 0x23E
U1BRG EQU 0x240
U1BRGHH EQU 0x242
U1RXREG EQU 0x244
U1TXREG EQU 0x248
U1P1 EQU 0x24C
U1P2 EQU 0x24E
U1P3 EQU 0x250
U1P3HH EQU 0x252


Notice that the U1MODEH EQU text, and others, has been changed to U1MODEHH EQU, which means the SFR is now recognised as a 32-bit type and the compiler will automatically produce the SFRs: U1MODE, U1MODEH, U1MODEHH and U1MODEHHH.


diebobo

Hi Les,

I am sorry to hear that Microchip makes lifer not easier, once more.. Anddddd i think there is more to come.. Did some testing with altered ppi file, and with some serial testing (HSEROUT) i only get 8 or 9 chars in 1 go out of the pic, the rest is not send.. That looks awfull alot like the TXbuffer. So i check the .ASM file once more and there is this part :

;------------------------------------------
; start of the compiler's library routines
.global __hrsout1
__hrsout1:
    btsc.w U1STAH,#pp_utxbf
    bra $ - 2
    mov.b WREG,U1TXREG
    return


If i understand this part btsc.w U1STAH,#pp_utxbf correctly, it is mend to check if tx buffer is full ? And it checkes the U1STAH register for that. With the altered ppi file it is checking the High byte of U1STA, but it should check U1STAHH.4  because that is the TX buffer full bit.. Think thats why i only get 8 chars on my serial monitor because that part of code isnt working anymore and it just overflows the tx buffer.

So if i am correct only altering ppi files isn't the solution cause that part of the asm file is created by your program which is hardcoded to use U1STAH ?? I sure hope not, but if it is then i would start pulling my hairs out for the needed changes :X The whole H added to a register system should the prob change,  it's not only the UART register who have this. A quick scan gives the following issues :

PCLH
QEI1IOCH
VEL1CNTH
QEI2IOCH
VEL2CNTH
U1MODEH
U1BRGH
U1P3H
U2MODEH
U2STAH
U2BRGH
U2P3H
SPI1CON1H
SPI1CON2H
SPI2CON1H
SPI2CON2H
SPI3CON1H
SPI3CON2H
NVMADRH
NVMSRCADRH
PTGBTEH
U3MODEH
U3STAH
U3BRGH
U3P3H

top204

Many thanks for your detailed examples.

I have changed the names of some SFRs in the .ppi files top match the earlier devices, so the name "U3STA" is now "U3STAL", and the bits references to the SFRs in the .def files have also been changed.

The "H" at the end of an SFR has always been to signify a high byte, but they are now using it to signify a high word, so it clashes with the compiler's H, HH, HHH mechanism for the seperate bytes of a variable or SFR. It got past me because the Asm30 assembler program should have thrown an error message for two .equ directives with the same name, and not assembled the code!

I've also made the changes to the compiler so it uses the new SFR names as well.

I'll upload a corrections update ASAP.


diebobo

Thanks Les.. will halt all work till update is available  :P

diebobo

Hi Les,

I saw there was un update for the compiler, unfortunatly the fix is not complete ( better though )..

The generated ASM ( See below ) for my used 33CK256MP502 still has doubble declared registers in it. The one that's stopping my show is U1MODEH which still has the 0x0239 and then 0x023a declared to it.. The compiler is using the latest Def file cause register U1STA is declared al the way to U1STAHHH, which is correct since the Def file is using the L and H markers.

.equ U1MODE, 0x0238
.equ U1MODEH, 0x0239
.equ U1MODEH, 0x023a
.equ U1MODEHH, 0x023b
.equ U1STA, 0x023c
.equ U1STAH, 0x023d
.equ U1STAHH, 0x023e
.equ U1STAHHH, 0x023f
.equ U1BRG, 0x0240
.equ U1BRGH, 0x0241
.equ U1BRGH, 0x0242
.equ U1BRGHH, 0x0243

I Filtered all the declares in the ASM file and the list below ALL are double declared and are in need of attention, all 25 of them :


PCLH
QEI1IOCH
VEL1CNTH
QEI2IOCH
VEL2CNTH
U1MODEH
U1BRGH
U1P3H
U2MODEH
U2STAH
U2BRGH
U2P3H
SPI1CON1H
SPI1CON2H
SPI2CON1H
SPI2CON2H
SPI3CON1H
SPI3CON2H
NVMADRH
NVMSRCADRH
PTGBTEH
U3MODEH
U3STAH
U3BRGH
U3P3H

top204

I've checked the PPI files and it looks as though I have missed a few, but some of the ones listed above are correct. For example, in the P33CK256MP502.inc file:

U1STAL EQU 0x23C
U1STAH EQU 0x23E
U1BRGL EQU 0x240
U1BRGH EQU 0x242
U1RXREG EQU 0x244
U1TXREG EQU 0x248

Notice that the SFRs now have an "L" after them, so the compiler will create the high byte name as "U1STALH", and not "U1STAH", which already exists, and the high byte of "U1STAH", will be "U1STAHH".

I'll go through the .ppi files again and upload them so they can be manually replaced. I'll also go through some of the .def files for the bit defines that I missed.

diebobo

Hi Les,

I am very sorry, this time i made a mistake. I mixed up the partnumbers in my reply and something else.. I was talking about the 33CK256MP502, but actually i am using a 33CK256MP205. The DEF en PPI file arent available for the 33CK256MP205 so i copy + renamed the 33CK256MP505 PPI and DEF files to 33CK256MP205.. Since the compiler don't have that files available i was accidently still using my older copy's of the 33CK256MP505 ones after the Update from last night...

So, sorry again this time and the first test seems to be oké now :)


top204

#10
We are only human diebobo, so we all make mistakes. It is the people who never admit to making mistakes that I cannot be bothered with, and I have worked for a few people like that in my time :-)

You have, thankfully, highlighted that I missed some of the more obscure SFRs in the dsPIC33xxCK ppi files, so I will go through them as well. I just wish the Asm30 assembler program did what it is supposed to do and give an error for a .equ that is duplicated, but that is what happens when a program is "open source". :-) When I get some time and settled back home in Norfolk, I'll go through the Asm30 source code and see if I can correct it, as I did with the gpasm assembler program a few years ago, when I was looking into using that instead of Mpasm, but it had far too many faults in its operation and did not cater at all for newer devices, without full re-writes.

diebobo

That's clear Les, and thanks for you kind words :) Howeverrrr, we are not out of the woods yet ( that's a correct saying right :o )..

I have some more, uhhh, anomaly's i guess.. I will just keep them in this post, if required new post let me know.. Got 3 thingy's, all of them still for same device :

1) - I think the HSERIN command is broken. Can't get it to work reliable and it seeeemsss that something goes wrong in the ASM with reading the buffer, mind 8 bytes instead of 4 of some previous devices ? .. The problem is HSERIN works delayed.. As in it's 8 chars delayed, so the HSERIN command reads the char that has entered the buffer 7 ( or 8 ) chars ago. This code to demonstrate :

Main:

Repeat
    HSerIn 100, Timeout_B, [Int_Serial_Char]
    hserout ["RX: ", Int_Serial_Char,10]

Until Int_Serial_Char = 10 Or Int_Serial_Char = 13    ' Linefeed or Cariage Return

Timeout_B:

GoTo Main

2)  UART Interupt ISR ( U1RXInterrupt ) does not work, in the ASM the wrong label ? is generated.. The following code :
 Isr U1RXInterruptgenerates in ASM :

.global __U1TXInterrupt
__U1TXInterrupt:

Mind in basic it says RX ( Receive ) in ASM it reads TX ( Transmit ).. Little bit strangggee :)


3) About the duplicated declares in ASM, did a scan and its limited to the following list.

QEI1IOCH
VEL1CNTH
NVMSRCADRH
PTGBTEH

Not a lot anymore, no idea what they are for but duplicated anyway..

My complete testprogram, only a short one so you can easy identifi it yourself..

Regards,

Bob

Device = 33CK256MP205
Declare Xtal = 100

Config FSEC     = BWRP_OFF, BSS_DISABLED, BSEN_OFF, GWRP_OFF, GSS_DISABLED, CWRP_OFF, CSS_DISABLED, AIVTDIS_OFF
Config FOSCSEL  = FNOSC_FRC, IESO_OFF
Config FOSC     = POSCMD_NONE, OSCIOFNC_ON, FCKSM_CSECMD, PLLKEN_ON, XTCFG_G0, XTBST_ENABLE
Config FWDT     = SWDTPS_PS2147483648, RCLKSEL_LPRC
Config FPOR     = BISTDIS_DISABLED
Config FICD     = ICS_PGD1, JTAGEN_OFF, NOBTSWP_DISABLED
Config FDMT     = DMTDIS_OFF
Config FDEVOPT  = ALTI2C1_OFF, ALTI2C2_OFF, ALTI2C3_OFF, SMBEN_STANDARD, SPI2PIN_PPS
Config FALTREG  = CTXT1_OFF, CTXT2_OFF, CTXT3_OFF, CTXT4_OFF
Config FBOOT    = BTMODE_SINGLE

Declare Hserial1_Baud = 115200

Dim Int_Serial_Char     As Byte

Clear

Setup:
'         5432109876543210
Ansela = %0000000000000000
TRISA  = %1111111111111111 ' A3/A4 = Button 1 & 2
AnselB = %0000000000000000
TRISB  = %1000001011111111
Anselc = %0000000000000000
TRISc  = %1111111111111110
Anseld = %0000000000000000
TRISd  = %1111111111111111 'D3 = Button 1

Osc_190MHz()                                ' Set the device to run at 190MHz

PPS_Unlock()                                ' \
PPS_Output(cOut_Pin_RP46, cOut_Fn_U1TX)    ' / Set the USART1 PPS pin
PPS_input(cIn_Pin_RP47, cIn_Fn_U1RX)    ' / Set the USART1 PPS pin

IFS0bits_U1RXIF = 0;
IEC0bits_U1RXIE = 1;   _U1RXInterrupt Enable

DelayMS 500

Main:

Repeat
    HSerIn 100, Timeout_B, [Int_Serial_Char]
    hserout ["RX: ", Int_Serial_Char,10]

Until Int_Serial_Char = 10 Or Int_Serial_Char = 13     ' Linefeed or Cariage Return

Timeout_B:

GoTo Main

end

Proc Osc_190MHz()

    CLKDIV = 0x3001; Dit is 100mhz
    PLLFBD = 0x96;
    OSCTUN = 0x00;
    PLLDIV = 0x32;
    ACLKCON1 = 0x8101;
    APLLFBD1 = 0x7D;
    APLLDIV1 = 0x21;
    CANCLKCON = 0x00;
    REFOCONL = 0x00;
    REFOCONH = 0x00;
    RPCON = 0x00;
    PMDCON = 0x00;
    PMD1 = 0x00;
    PMD2 = 0x00;
    PMD3 = 0x00;
    PMD4 = 0x00;
    PMD6 = 0x00;
    PMD7 = 0x00;
    PMD8 = 0x00;

    Write_OSCCONH($01)
    Write_OSCCONL($01)

    While OSCCONbits_OSWEN <> 0 : Wend  ' Wait for the clock switch to occur
EndProc

Isr U1RXInterrupt

    IFS0bits_U1RXIF = 0 ' Als m hier niet reset, en er komt een nieuwe binnen terwijl de routine nog niet klaar is pakt ie de interrupt niet.. Baluh !

    HSerOut ["*** Serieel ontvangen ", 10]

    IFS0bits_U1RXIF = 0    ' hier nog een keer resetten omdat er gewoon is blijven ontvangen door de uart terwijl we m bovenaan alweer gerest hadden... Dan keert het programma weer terug naar interupt en dan is er niets meer te ontvangen = timeout..

EndIsr

charliecoutas

diebobo: Which 33CK chip size are you using? I am about to start using a 33CK256MP505 but the only footprint I can get is a TQFP48 which is tiny. About 7mm across opposite pins and I'm not sure if I can handle such a small device physically.

Charlie

diebobo

Hi Charlie,

I am using a TQFP48. And yes its small, but smaller is also doable. Atleast the TQFP packacge has some decent length pins to solder to. Think all depends on your skill and equipment.. What are you doubt's to be able to handle so such device ? Eye's, solder skills ? If it's solder skill then using good solder iron/point and good flux does the job. As well good brand of wick ( no cheap china wick )..

John Lawton

I'm a believer in getting an expert to do a task. Someone with the eyes, tool and experience to do the job. That's why apart from prototypes I get my boards professionally built.

Having said they, assembling my own prototype bit me hard this year as I had a lot of issues with one small board, all due to my hand soldering of some SMT parts.

John

top204

I'm busy correcting the subtle difference on the CK devices for receive. It uses the the E bit, not the F bit to signal a byte is ready in the buffer.

I've ran some RX/TX interrupts on them and they do not give any errors.

I'll have a corrections update ready ASAP.

charliecoutas

I managed to handle the uMAX8 size of smd and the TQFP48 is only a little smaller between pins. Thanks for the help, I'll try it. "Feint heart never did something or other"

Charlie

top204

#17
Charlie, John...

If you are having issues with SMD soldering for a prototype board, post it to me with the components that you are having problems with, and I will solder them for you. It would be my pleasure. :-)

I've worked with SMD components for about 25 years now and I have a good stereo microscope, good lighting, and an excellent Pace soldering station, so they are not a problem for me. I've just finished a prototype board for myself with 0402 components on it, and they are "really" small. LOL

charliecoutas

Thanks Les, I might take you up on that. A kind offer.

Charlie

charliecoutas

diebobo

Do you use the ADC in the 33CK devices? I am getting "Linker error:'a.o(.text+0x8a).....undefined reference to ad1con3'"


   Dim  adc_result As Word
Main:  adc_result = ADIn 0

Sorry Les if this is my fault.