Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 02:21 05 Feb 2023 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Hoping for some MPASM Assembler help.

     Page 1 of 2    
Author Message
Bowden_P
Senior Member

Joined: 20/03/2019
Location: United Kingdom
Posts: 119
Posted: 11:53pm 19 Jan 2023
Copy link to clipboard 
Print this post

Hi,
I'm looking for some help with an MPASM assembler program which isn't playing ball, and I can't see why. ( No surprise there then!)

The device I'm using is a Microchip PIC16F1776.

The code is a test for outputting values from a sample table to a DAC to generate a waveform. Followed by a low pass filter, it is intended produce a reasonable sine wave. This is quite a standard way of waveform synthesis, and should be "easy" to do. It will form part of a MM2 project if it ever gets to work.

The problem lies in the interrupt code, responsible for recovering the current sample and outputting to the on-chip DAC. The DAC output stubbornly refuses to change from its initialised value. In fact the programming is all in the Interrupt Service Routine - the Main Loop is just a string of NOP's !

By toggling output pins I have shown :-
1. The Main Loop is running.
2. The Clock oscillator is running at the programmed frequency - 32MHz.
3. The ISR is being called - timed by a PWM source - again at the expected frequency - 10KHz.
4. Flag sorting in the ISR is functioning as expected, and the ISR "can" be made to change the DAC o/p from the initialised state,
  toggling it from two table end-to-end values with the expected amplitude.

The ISR just woun't pull values off the sample table and manage its pointer on a continuous basis.

Here is the ISR :-

DAC Test Program Code.zip

With best regards, Paul.
Nothing so constant as change.
 
Bowden_P
Senior Member

Joined: 20/03/2019
Location: United Kingdom
Posts: 119
Posted: 01:19pm 22 Jan 2023
Copy link to clipboard 
Print this post

Hi All,
Many thanks for all that viewed my request.

Obviously not quite the "flavour of the month" it seems. †

However, after a lot of debugging it appears that the instruction "MOVIW FSR0++" and its twin "MOVIW FSR0--" for recovering data from a table doesn't work as expected and is faulty, with no automatic decrement/increment after the data read.

So Me one † - Microchip zero. †

The device is PIC16F1776, rev A1, which doesn't appear to have been revised since Feb-2016.

What to do now?

With best regards, Paul.
Edited 2023-01-22 23:20 by Bowden_P
Nothing so constant as change.
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 3327
Posted: 03:04pm 22 Jan 2023
Copy link to clipboard 
Print this post

I gave MPASM as miss as much as possible. IIRC I had to load it to set up a PicKit originally, but after that I got rid of it and stock to GCBasic. :)  The MPASM package was simply too big and clunky to be wasting disk space on for me.

The PIC16F1776 is relatively new by my standards. lol

Sorry, I'm not much use on this am I?
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
stanleyella

Guru

Joined: 25/06/2022
Location: United Kingdom
Posts: 509
Posted: 03:33pm 22 Jan 2023
Copy link to clipboard 
Print this post

PIC16F1776 probably supported in gcbasic with pickit plus
 
vegipete

Guru

Joined: 29/01/2013
Location: Canada
Posts: 956
Posted: 05:25pm 22 Jan 2023
Copy link to clipboard 
Print this post

Two comments: (neither of which will help your issue.)

Use "BANKSEL" instead of "movlb" - this way you don't have to look up which register is in which bank.

For example, avoid
isr_pwm5_start ; Pointer Incrementing or Decrementing ?
   movlb   bank_27        ; ( Bank 27.)
   bcf     PWM5INTF,PRIF  ; Clear the PWM5 Period Interrupt flag,

Instead, use
isr_pwm5_start ; Pointer Incrementing or Decrementing ?
   banksel PWM5INTF       ; ( Bank 27.)
   bcf     PWM5INTF,PRIF  ; Clear the PWM5 Period Interrupt flag,


2) Can you put things like "flags" into common ram? (address 70h to 7fh) Then you won't need to switch banks to access them.

=============
Is your table direction handling correct? The comments suggest the flag is set to 0 to count up, just after you set the index to the end (-1) of the table, not the beginning.

Have you tried running this in the simulator? Does that show anything interesting?

There's no bank boundary crossing going on? The table ends are positioned 'nicely'?

Do pre-increment and decrement show the same behaviour?

Maybe you will be stuck with manually moving FSR0L up and down, and reading through INDF0. Fortunately, FSR0L and INDF0 are core registers and accessible from all banks.
Visit Vegipete's *Mite Library for cool programs.
 
zeitfest
Senior Member

Joined: 31/07/2019
Location: Australia
Posts: 282
Posted: 10:09pm 22 Jan 2023
Copy link to clipboard 
Print this post

(Its a long time since I used assembly so very rusty but ..)

(edited after checking the instruction code doc † ) does it give the same result if the autoincrement is left out ?

MPASM was reliable AFAIK.

(added) †are the FSR's preserved when interrupts happen ? I vaguely remember some registers have undefined contents when an interrupt starts, and having to store/refresh values. Some are "shadowed" ok for the interrupt but changed values are not written back for the main code, so the next interrupt only sees the original value
Edited 2023-01-23 15:56 by zeitfest
 
Bowden_P
Senior Member

Joined: 20/03/2019
Location: United Kingdom
Posts: 119
Posted: 12:20am 26 Jan 2023
Copy link to clipboard 
Print this post

Wow, many thanks for all replies!

Hi Mixtel90,
I've become a bit wary of relatively "new" devices from Microchip, and always check the errata datasheet before deciding whether a chip is worth trying. This one didn't seem too faulted, so went ahead. I think it's appalling that they even consider selling a chip with known faults, but they do frequently. ( I must admit an instruction fault is very rare in my experience.)

Hi Stanleyella,
I haven't worked with GCBASIC - will have to look at that. However, it would not fix a chip fault sadly!

Hi Vegipete,
Thanks for the "banksel" prompt. I tend to use the "movlb" instruction mostly. I find knowing the bank a register is in can help order instructions accessing banks more efficiently - just my preference I guess. There is always the temptation to use it to excess before every access which then slows execution down. I'm always keen to minimise on timing !

BTW - I'm kicking myself on not using the common registers - thanks for that suggestion. In the past I treasured them as there is only 16 of them, and they got used all too quickly, so didn't consider using them in this short program.

Table direction - ah-ha. When I comment "UP" I am imagining the register bank as a column, with the low location (say h'20') at the TOP so going up the table requires decrementing the table pointer! (The "end" of the bank is say h'6F' which is down/incrementing.) I take your point - not so intuitive is it!

Not tried the simulator, and definitely no bank or page crossing here - another gotcha from my past experience with MPASM!

For the time it took to discover the instruction fault I was anxious to get some results, so didn't make mods to use a pre-inc/dec trial. (It might have worked.) The solution I used was to put the sample data table in program memory and access in a subroutine call with "BRW" and "RETLW nn" - instant success. This avoided any indirect access completely.

Hi Zeitfest,
Manually manipulating FSR0 with INDF did nearly work - just 1 sample was wrong - the most -ve output from the DAC. This was wierd, and consistent when using either the 5-bit or 10-bit DAC's. I decided not to pursue that one.

Context saving and restoring is automatic on the "advanced" PIC16F1xxx chips - including the FSR's, which saves time in interrupts and is so convenient. I have never used the shadow registers so far and am unsure why they are present - why not just address the originals if you want to change them?

I might try contacting Microchip about their instruction error - but in the past their forum feedback was very negative, with posters often complaining of non-response.

Thanks again for all your posts,
With best regards, Paul.
Nothing so constant as change.
 
zeitfest
Senior Member

Joined: 31/07/2019
Location: Australia
Posts: 282
Posted: 06:52am 26 Jan 2023
Copy link to clipboard 
Print this post

Just for general info - maybe it helps

data sheet p 107

7.5 Automatic Context Saving

Upon entering an interrupt, the return PC address is
saved on the stack. Additionally, the following registers
are automatically saved in the shadow registers:
ē W register
ē STATUS register (except for TO and PD)
ē BSR register
ē FSR registers
ē PCLATH register
Upon exiting the Interrupt Service Routine, these registers are automatically restored. Any modifications to
these registers during the ISR will be lost. If modifications to any of these registers are desired, the corresponding shadow register should be modified and the
value will be restored when exiting the ISR. The
shadow registers are available in Bank 31 and are
readable and writable. Depending on the userís
application, other registers may also need to be saved.
 
Bowden_P
Senior Member

Joined: 20/03/2019
Location: United Kingdom
Posts: 119
Posted: 03:29pm 26 Jan 2023
Copy link to clipboard 
Print this post

Hi Zeitfest,
Thanks for the quote. I guess my skill in using assembler hasn't required such mods in an interrupt. I do remember experimenting with decrementing the stack pointer in a call within a call to a subroutine, to return up 2 levels directly as an exit manoeuvre, but wasn't that confident in doing it.

I did mod my interrupt code to use the pre-increment/decrement instruction variant of "moviw" - and that didn't work either - not really a surprise there. The DAC o/p moved one step from its initial level only.

It's amazing what assembler can achieve with a bit of planning. Years ago back in the days of home computers (ZX81 and Amstrad CPC6128 in my case,) I found assembler very compact and speedy, and developed a model railway turntable controller hung off the expansion port of the 6128. The program was almost 5K long and mostly worked first time except for a few small errors. Stepper motor driven, auto-calibrating to tracks, with auto track power switching, controlled acceleration and deceleration too. Great fun and a strong sense of achievement when it all finally worked.

With best regards, Paul.
Nothing so constant as change.
 
zeitfest
Senior Member

Joined: 31/07/2019
Location: Australia
Posts: 282
Posted: 10:26pm 26 Jan 2023
Copy link to clipboard 
Print this post

I wish there was more assembler discussion here on TBS ! your post really sparked the interest again. I haven't used it for quite a while, even then I was scratching the surface at the single-level interrupt level. Exasperating but there is something about working at the raw metal .
I concentrated on C instead, the main reason was via a bout of crippling sciatica/disk problems and business recession .. on unemployment benefits scheme I registered as skills/experience in science and programming including assembly and other languages, etc. †Govt agency directs me to a signmaking factory ... assembling signs. † † †It is many years ago but somehow it stays in my memory †
Edited 2023-01-27 08:28 by zeitfest
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 3327
Posted: 10:39pm 26 Jan 2023
Copy link to clipboard 
Print this post

Many years ago I played with a Z80 macro assembler. Being able, at that time, to create my own "commands" then string them together to form a program was rather cool. :)  I don't think I've touched assembler since though. We were all in awe of the bloke who wrote the monitors for the Nascom computers. He hand assembled the first one using pen and paper, which filled a 1k EPROM, and it ran first time.
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
Bowden_P
Senior Member

Joined: 20/03/2019
Location: United Kingdom
Posts: 119
Posted: 12:19am 27 Jan 2023
Copy link to clipboard 
Print this post

Hi Zeitfest and Mixtel90,
I had a similar experience when made redundant in 2004. After signing on and stating by previous job as a Product Engineer ( with a semiconductor manufacturer ) they offered me work in a food factory!

I remember using a ROM based assembler which plugged into my CPC6128 via a ROMBOX for Z80 assembly programs. It was remarkably fast given the machine's 4MHz clock, and none of this single cycle instruction execution we have in PIC's. You could hop to and from BASIC and assembler, enabling screen functions with the assembly. ( I also had a PASCAL ROM, but didn't get on with that. There were a couple of other ROMs too, but I don't recall what they did.)

With best regards, Paul.
Nothing so constant as change.
 
JimDrew
Newbie

Joined: 07/10/2020
Location: United States
Posts: 35
Posted: 05:42am 01 Feb 2023
Copy link to clipboard 
Print this post

Hello Paul... I am LONG time PIC assembly programmer.  I have been working daily with PIC parts since there were only the 12C508 in a UV erasable part - circa 1999.  In the last 20+ years I have developed more than 300 commercial products using PIC micros, all of them written in assembly.  Today, I still work with PIC assembly code but primarily on the dspIC33Cx series.  I do still occasionally still use some of the PIC12, PIC16, and PIC18 parts when a low pin count option is possible (again, all in assembly - I have never written a C coded program for PIC micros).  For legacy parts I still use MPLAB8, but for modern parts I use MPLAB-X.  I am a big fan of the simulator, but I primarily used the MPLAB ICE, which I recently replaced with the MPLAB ICD4.  Real-time in-circuit debugging at the assembly code level is the way to go - there are no mysteries.

I looked at your code and I have to agree with someone who said not to use MOVLB for bank selection. You should be using the built-in MACRO that MPASM has to handle bank selection.  Using the MACRO absolutely guarantees that you will not have the wrong bank selection and although datasheets do sometimes have the wrong data (something like a PWM peripheral shown in the wrong bank), that problem will not exist with the assembler's MACROs.

If you refer to page 141 of the datasheet (DS40001810B) for your PIC16F1776 part you will see an example of proper bank selection.  In fact, you will never find any example code using MOVLB because the MACRO takes care of the odd cases from part to part that you might not know about.  You will also notice in this example that using FSR0++ is perfectly acceptable.  You can also use FSR0-- as well.  See page 496 of the datasheet.  You can do both post and pre inc/dec with FSR0 and FSR1.  I use this extensively with this family of parts in commercial products, so there is no question of the MOVIW and MOVWI instructions not working, they do.

So.. looking at your code, I would guess right off that since you say FSR0 is not changing as expected that the issue is with your table handler... OR, the issue is with the DAC setup and usage.  I don't have any experience with this particular part's DAC, but a glance at the datasheet reminds me that the ADC and DAC can be set for their bit justification (left or right justified).  Make sure you have that set to what you are expecting for your table data.

My best guess is that your table handler is not logically correct.  You need to make sure you have your SUBLW instructions correct.  This is not a standard subtract in the traditional sense, but a 2's compliment instead.  This whole issue became so confusing to me that I actually still use an inverted ADDLW when I need to subtract a value because there are no gotchas with that instruction.  I would recommend that you walk through your code with the simulator and make sure that your table lookup is actually working the way you intend.  Since you are doing a simple FSR0-- and FSR0++ (a single DEC and single INC) you could just compare the low byte of FSR0 using an XOR instead of the subtract method you are using now, ie:

movwf FSR0L,w
xorlw LOW wf_tbl_top
btfss STATUS,Z

Sorry I can't be of more help, but your entire project was not included so I can't see your MPLAB settings or your setup for various registers.

I have been programming in assembly code since the late 70's, starting with the 6502, going to the Z80, 680x0, 80x86, PICs, AVRs, and nowadays Risc-V parts.  I have written a couple of programs in assembly code that were both more than 1.6 million lines of code.  With the advances in micros having giant amounts of memory and code space, higher level languages have really taken over so there are not a lot of us old assembly coders left.  However, for what I do there is really no option to use higher level languages without a huge headache to be DO-178C compliant, not to mention to be able to cycle count for accuracy/repeatability.
Edited 2023-02-01 16:05 by JimDrew
 
Bowden_P
Senior Member

Joined: 20/03/2019
Location: United Kingdom
Posts: 119
Posted: 03:10am 02 Feb 2023
Copy link to clipboard 
Print this post

Hi JimDrew,
Many thanks for your time and thought to put together your comprehensive post !

I prefer to use MOVLB rather than your suggested BANKSEL, just to know that I understand what bank my program is supposed to be addressing. There is always the temptation to over-use it with out needing to if registers are in the same bank - you wouldn't know if you never looked !! That's definitely me being over-controlling I guess, but I'm always keen to trim assembly code down to the bone if at all possible - something to do with my initial experiences with very limited memory Z80 and early PIC devices.

It wouldn't surprise me if there was an error in my table/pointer management that I just can't see. I'd love the MOVIW FSR0--/++ instruction to work fetching data from GPR's as it is marginally faster than using program memory, but as outlined in my previous posts, the instruction only worked in my code if the FSR0 register was also incremented/decremented beforehand - a bit pointless using MOVIW in that case !!

For most of my projects I've used MPLAB v8.91, but this device was not included in that, so it has been written using MPLABX v3.65. ( Why v3.65 and not v6.0 ? - that's because I've recently moved from XP to Win10, but haven't got assembly working on V6.0 yet - but that's a problem for another day!)

Regretably it's getting a bit late now - but if you would be so generous to look over my code - I'll put together a tidied full program .zip tomorrow. If you can spot the error(s) - I would be most grateful.

With best regards, Paul.
Nothing so constant as change.
 
JimDrew
Newbie

Joined: 07/10/2020
Location: United States
Posts: 35
Posted: 06:14am 02 Feb 2023
Copy link to clipboard 
Print this post

You can't "over-use" the BANKSEL function.  It's the exact same thing as using MOVLB, except it guarantees that the bank will always be correct because it comes from the assembler's first pass.  Where ever you put a MOVLB <bank>, just put a BANKSEL <addr>.  There is no difference in code size because the assembler will use MOVLB with modern parts or a series of instructions (with PCLATH when necessary) for the legacy parts. This makes porting code from one part to another MUCH easier.  Even with the modern parts, just moving from one part to another in the exact same family can cause the banks to switch.  This is very common with the 16F153xx and other parts.

I use MPLAB 8.92 (the last of that original 8.x IDEs), and I have one setup for MPLAB-X 5.35 because that was the last version of MPLAB-X to support the MPASM assembler.  After that, you are stuck using XC8's assembler which means a whole host of changes that I was not willing to do.  I use the latest version of MPLAB-X for the PIC24 and dsPIC33 parts, using XC16's assembler.

The MOVIW and MOVWI instructions *always* work, regardless of the post/pre inc/dec.  So, I am sure this is just some logical issue that can be pretty easily resolved.  If you want to put together the MPLAB-X project I would be happy to do a quick walk through and check out your table lookup.

I am a huge believer in saving even 1 cycle time if possible - cycle counting is kind of my thing, and it's why I love assembly. You have total control of what is going on.  I have disassembled/reverse engineered some large projects (like Apple's Mac OS) and the amount of bloat from C code is just astounding.  In our modern times people can just add more memory and CPU horsepower, and it doesn't matter anymore - except it does because you could be that much faster and probably use a smaller/cheaper part.  Before Microchip bought Atmel, I made a killing from converting AVR compiled code into PIC assembly code.  This often times resulted in 1/2 the code space requirement and a smaller/cheaper chip requirement.


Jim
Edited 2023-02-02 16:26 by JimDrew
 
vegipete

Guru

Joined: 29/01/2013
Location: Canada
Posts: 956
Posted: 05:14pm 02 Feb 2023
Copy link to clipboard 
Print this post

  Quote  You can't "over-use" the BANKSEL function.
I sympathize with Paul's desire not to over-use BANKSEL.

Consider this setup code for, say, a '16F1776:
  movlw   0x8F
  BANKSEL TRISA
  movwf   TRISA
  movlw   0x16
  BANKSEL TRISB
  movwf   TRISB

On the one hand, the second BANKSEL is not needed, because both TRIS registers are in the same bank. However, the code might break if ported to a different chip with reorganized register placement.

I prefer to minimize BANKSELs by grouping same bank accesses together when possible. Better yet, use a PIC18 or PIC24/dsPIC33.

Jim, thanks for the tip about MPLAB-X 5.35 being the last version to support the MPASM assembler. Good to know. I've been lazy lately using XC8 and C. The bloat is staggering...
Visit Vegipete's *Mite Library for cool programs.
 
Bowden_P
Senior Member

Joined: 20/03/2019
Location: United Kingdom
Posts: 119
Posted: 11:49pm 02 Feb 2023
Copy link to clipboard 
Print this post

Hi Jim,
Thanks too for the MPLABX v5.35 tip - I feel a legacy download coming on soon !

I have included here a .zip of the 4 files I use for this DAC Code trial program.

DAC_Code.zip

There's one .asm and 3 .inc files.

I've not included the MPLABx files as my ancient v3.65 version may not be compatible with your v5.35.

Thanks for any pointers you can give me.

The bulk of the code is in the interrupt routine - not very long, and there are several alternative versions commented there too.

Some other commented code is also present in other files, marked "DEBUG".

With best regards, Paul.
Nothing so constant as change.
 
JimDrew
Newbie

Joined: 07/10/2020
Location: United States
Posts: 35
Posted: 12:32am 03 Feb 2023
Copy link to clipboard 
Print this post

  vegipete said  
  Quote  You can't "over-use" the BANKSEL function.
I sympathize with Paul's desire not to over-use BANKSEL.

Consider this setup code for, say, a '16F1776:
  movlw   0x8F
  BANKSEL TRISA
  movwf   TRISA
  movlw   0x16
  BANKSEL TRISB
  movwf   TRISB

On the one hand, the second BANKSEL is not needed, because both TRIS registers are in the same bank.


Yes, but this is really the same as when using the MOVLB instruction - in fact, that is what the assembler generates for this family of parts when BANKSEL is used.  There is literally no difference, EXCEPT you can port your code between families of chips without any worries about using the wrong bank.  Microchip actually frowns upon anyone using MOLVB because this has always been a tech support nightmare ever since this instruction was introduced due to the fact the banks can change between parts.  You will not find many datasheets even showing the use of MOVLB in place of BANKSEL, and for good reason.  At any rate, just keep in mind that Microchip was not very good at retaining compatibility between parts, even those in the same family.  :)

BTW, MPLAB-X v5.35 is the first version where MPASM does not support 64 bit Windows - except that is not actually true! It does, but you see this error message:

MPASM is not supported on 64 bit Operating Systems. Please consider migrating your project "DECS_PT" configuration "ICD4" to XC8 Assembler or continue to use a previously released IDE.

The *next* version (5.40) is the one that enforces the 32 bit requirement, and then I think it was the next version after dropped support completely for MPASM.  For all practical purposes on modern machines, v5.35 is the latest one usable with MPASM.
 
JimDrew
Newbie

Joined: 07/10/2020
Location: United States
Posts: 35
Posted: 02:06am 03 Feb 2023
Copy link to clipboard 
Print this post

I will grab your archive, create the project and take a look.
 
JimDrew
Newbie

Joined: 07/10/2020
Location: United States
Posts: 35
Posted: 04:16am 03 Feb 2023
Copy link to clipboard 
Print this post

So... I created a project and looked over the entire project to see what it is that you are trying to do.  It seems that you setup PWM5 to generate a pulse every 'x' number of cycles, and PWM5 is setup to generate an interrupt when the there is a transition change.  You set the PWM5 output on pin RC3 via PPS.

I can walk through with the simulator and everything works - except no interrupt is generated. ¬†I even tried using the Stimulus to force a pin change and that does not trigger the ISR. ¬†I need to look at your PWM5/interrupt setup. ¬†The PWM5 is toggling correctly. ¬†I enabled a pin trace in the simulator and it definitely does toggle when it is suppose to, but no interrupt is generated. ¬†This could be just one of those "things" with MPLAB-X where the interrupt is not supported through the simulator, but I have only seen that once before and it was corrected with a newer version of MPLAB-X. ¬†I don't think that is the case here, but I can go back and look at the release notes.  I am using v5.35 for this testing.

I will tinker with this some more. ¬†If I can't get it to trigger the interrupt (so the PC jumps to the ISR), I can manually move the PC to the ISR and simulate the trigger, and then walk through.  The goal of this seems to be generating a sinus output via the DAC.
Edited 2023-02-03 14:55 by JimDrew
 
     Page 1 of 2    
Print this page
© JAQ Software 2023