CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

[SOLVED] PIC16LF18445, NVM PMD Affecting UART

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
newguy



Joined: 24 Jun 2004
Posts: 1908

View user's profile Send private message

[SOLVED] PIC16LF18445, NVM PMD Affecting UART
PostPosted: Wed Oct 28, 2020 1:21 pm     Reply with quote

Took me a while to diagnose the cause of a weird issue I was seeing. I'm at the point now where I'm not sure if it's the compiler or if it's an undocumented errata on the processor. Long story short, disabling the non-volatile memory via its peripheral module disable (PMD) bit ends up causing issues with the UART.

Project has a PIC16LF18445 processor. First program after I soldered the prototype was a bog standard flash an LED at a set rate. That worked. Moved on to testing the serial connection to the outside world and that's where I've sat for way too long. I've managed to diagnose the cause but I have no idea why. Stripped down test program that demonstrates the problem follows.

Compiler version 5.093

Code:
#include <16LF18445.h>
#device ADC=12

#FUSES NOEXTOSC              //External Oscillator not enabled
#FUSES RSTOSC_HFINTRC        //On Power-up clock running from HFINTRC
#FUSES NOCLKOUT              //I/O function on OSC2
#FUSES NOCKS                 //Clock Switching Disabled
#FUSES NOFCMEN               //Fail-safe clock monitor disabled
#FUSES MCLR                  //Master Clear pin enabled
#FUSES PUT_64MS              //Power-Up timer set to 64ms
#FUSES NOLPBOR               //Low-Power Brownout reset is disabled
#FUSES NOBROWNOUT            //No brownout reset
#FUSES ZCDDIS                //Zero-cross detect circuit is disabled at POR
#FUSES PPS1WAY               //Allows only one reconfiguration of peripheral pins
#FUSES STVREN                //Stack full/underflow will cause reset
#FUSES NODEBUG               //No Debug mode for ICD
#FUSES WRTD                  //Data EEPROM write protected
#FUSES NOLVP                 //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES PROTECT               //Code protected from reads

#use delay(internal=4000000)

#pin_select U1TX = PIN_C6
#pin_select U1RX = PIN_C7
#use rs232(baud=57600, UART1, errors, STREAM=CONFIG)

#case

#use fast_io(C)

#byte PMD0 = getenv("SFR:PMD0")
#define PMD0_NVM_DISABLED           0x04

#define DEBUG_LED_PIN               (PIN_A4)
#define DEBUG_LED_ON()              (output_low(DEBUG_LED_PIN))
#define DEBUG_LED_OFF()             (output_high(DEBUG_LED_PIN))

void main(void) {
   output_c(0x40);
   set_tris_c(0x80);

   // general delay to allow everything to stabilize
   delay_ms(250);
   
   // flash the LED
   DEBUG_LED_ON();
   delay_ms(100);
   DEBUG_LED_OFF();

   PMD0 = PMD0_NVM_DISABLED; // this line causes the UART to stop transmitting***
   // comment out above line and PIC transmits "Ready\r\n" every 100ms

   while(TRUE) {
      output_toggle(PIN_A4);
      fprintf(CONFIG, "Ready\r\n");
      delay_ms(100);
     
   }
}


During my diagnosis/troubleshooting of this issue I found that if the total number of characters I attempt to transmit is 3 or less, the UART actually keeps transmitting even if the non-volatile memory module is disabled per the line above. That was a fun one to diagnose. In all cases, the LED flashes at a 5Hz rate whether the UART actually transmits or not. Verified that the PIC's TX line sticks high with an oscilloscope when the issue manifests.

Relevant bit from the list file:
Code:
....................    PMD0 = PMD0_NVM_DISABLED; // this line causes the UART to stop transmitting***
00B4:  MOVLW  04
00B5:  MOVLB  0F
00B6:  MOVWF  PMD0


I'm unfamiliar with the memory mapping of this processor, so I'm unsure if the proper bank is being selected. The data sheet shows that PMD0 is at offset 0x0796 but I have no idea how that maps to a particular bank, nor if bank F is correct.

Any help would be appreciated. This is a very low power battery operated device; that's why I have to directly power down modules that aren't used.


Last edited by newguy on Thu Oct 29, 2020 10:55 am; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Thu Oct 29, 2020 2:37 am     Reply with quote

The code uses PFM reads, to read things like the string "Ready\r\n".
This is why PFM reads must not be turned off in the config registers.
Disabling the NVM bit, prevents read access. Hence the code is
unable to read the string once this bit is set....
Quote:

NVMMD

All Memory reading and writing is disabled; NVMCON registers cannot be
written; FSR access to these locations returns zero.


Code:

#include <16LF18445.h>
#device ADC=12

#FUSES NOEXTOSC              //External Oscillator not enabled
#FUSES RSTOSC_HFINTRC        //On Power-up clock running from HFINTRC
#FUSES NOCLKOUT              //I/O function on OSC2
#FUSES NOCKS                 //Clock Switching Disabled
#FUSES NOFCMEN               //Fail-safe clock monitor disabled
#FUSES MCLR                  //Master Clear pin enabled
#FUSES PUT_64MS              //Power-Up timer set to 64ms
#FUSES NOLPBOR               //Low-Power Brownout reset is disabled
#FUSES NOBROWNOUT            //No brownout reset
#FUSES ZCDDIS                //Zero-cross detect circuit is disabled at POR
#FUSES PPS1WAY               //Allows only one reconfiguration of peripheral pins
#FUSES STVREN                //Stack full/underflow will cause reset
#FUSES NODEBUG               //No Debug mode for ICD
#FUSES WRTD                  //Data EEPROM write protected
#FUSES NOLVP                 //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES PROTECT               //Code protected from reads

#use delay(internal=4000000)

#pin_select U1TX = PIN_C6
#pin_select U1RX = PIN_C7
#use rs232(baud=57600, UART1, errors, STREAM=CONFIG)

#case

#use fast_io(C)

#byte PMD0 = getenv("SFR:PMD0")
#define PMD0_NVM_DISABLED           0x04

#define DEBUG_LED_PIN               (PIN_A4)
#define DEBUG_LED_ON()              (output_low(DEBUG_LED_PIN))
#define DEBUG_LED_OFF()             (output_high(DEBUG_LED_PIN))

void main(void) {
   char temp_str[20]; //ram buffer
   int ccnt;
   output_c(0x40);
   set_tris_c(0x80);

   // general delay to allow everything to stabilize
   delay_ms(250);
   sprintf(temp_str, "Ready\r\n");
   //put the message into RAM
   
   // flash the LED
   DEBUG_LED_ON();
   delay_ms(100);
   DEBUG_LED_OFF();

   PMD0 = PMD0_NVM_DISABLED; // this line causes the UART to stop transmitting***
   // comment out above line and PIC transmits "Ready\r\n" every 100ms

   while(TRUE) {
      output_toggle(PIN_A4);
      for (ccnt=0;ccnt<strlen(temp_str);ccnt++)
         fputc(CONFIG, temp_str[ccnt]); //print from RAM
      delay_ms(100);
     
   }
}   


Shows a potential way to 'pregenerate' the output string in RAM, and
send this.

The read returning zero, means that the printf, won't output anything,
so no UART writes will occur.... So it is not the 'UART' being affected,
but the ability to read from the program memory to retrieve what is
to be sent....
newguy



Joined: 24 Jun 2004
Posts: 1908

View user's profile Send private message

PostPosted: Thu Oct 29, 2020 9:06 am     Reply with quote

Thanks Ttelmah. A clear case of not reading the data sheet to be sure. I had done several equivalent projects (battery powered, very low current draw) but with an 18 series PIC, and disabling the NVM on that chip disabled the EEPROM only. I was expecting similar behaviour. What really threw me was the fact that strings with lengths of 1, 2 or 3 characters would successfully be sent. Why that worked at all given that they shouldn't ever have worked is beyond me. I suppose I should dust off my Microchip support login and let them know about this weirdness.
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Thu Oct 29, 2020 9:33 am     Reply with quote

CCS doesn't bother to add the NVM access code for single characters,
or very short strings. They instead hard code the bytes. The access
costs quite a few bytes of program size, so not worth it for just a couple of
characters.
It's not really an oddity. It is doing what it says. You turn off the section
that allows access to NVM. If you then try to read the NVM, don't
be surprised if it doesn't work!...
newguy



Joined: 24 Jun 2004
Posts: 1908

View user's profile Send private message

PostPosted: Thu Oct 29, 2020 9:55 am     Reply with quote

I'm now wondering if the "working" 18-series projects I've done before where I also disabled the NVM unless I was reading/writing the internal EEPROM weren't actually supposed to work at all....

...In those, code flow was identical; plenty of hard-coded strings being sent via the UART, and those projects functioned correctly.
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Thu Oct 29, 2020 10:32 am     Reply with quote

I suspect you are talking a different NVM access restriction.
If you look the NVM restriction created by the _protection_ system, turns
off the access from a programmer, not from the code. Hence the code
access keeps working.
Turning off the NVM read hardware is not possible on most chips.
newguy



Joined: 24 Jun 2004
Posts: 1908

View user's profile Send private message

PostPosted: Thu Oct 29, 2020 10:55 am     Reply with quote

It's simply a matter of me not reading the data sheet because I assumed it was going to have the same behaviour as an 18-series processor I had dealt with before. This processor's additional restriction on not being able to read program flash (i.e. ROM strings stored therein) when the NVM's PMD has been activated is not something I anticipated. I assumed that only the EEPROM would be deactivated.

Going back to the 18-series for a moment - I suppose that Microchip's nomenclature could have been more specific. On that processor they called the EEPROM disable "non-volatile memory (NVM)" but EEPROM would have been more appropriate. For this processor, NVM is entirely appropriate because it does "kill" read access to pretty much everything - but I assumed it was just going to restrict accesses to only the EEPROM, since that's what the PMD of the same name did on the 18 I was used to.

At any rate, problem averted thanks to your generous help/guidance (as always)! I'll edit the title to add [SOLVED].
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Fri Oct 30, 2020 1:59 am     Reply with quote

Yes, makes total sense.
They are all 'parts' of the NVM, and the PMD function disables it all, while
the protection functions have options to disable it only for external
programmer or for the EEPROM only. It would make a lot more sense
to use the names defining what parts are affected... Sad
newguy



Joined: 24 Jun 2004
Posts: 1908

View user's profile Send private message

PostPosted: Fri Oct 30, 2020 8:08 am     Reply with quote

Just did one last check. The 18-series project I've mentioned that worked despite a similar program structure had one key difference:

Code:
#device PASS_STRINGS=IN_RAM


I just added that to the PIC16 program above and it didn't make any difference. I thought that one line might have been why the 18 program worked but this one didn't, but that's not the case.
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Fri Oct 30, 2020 8:32 am     Reply with quote

No, The Pass_strings option means a temporary buffer is used, but the
data still has to be read from the program memory.

What chip were you using?.
newguy



Joined: 24 Jun 2004
Posts: 1908

View user's profile Send private message

PostPosted: Fri Oct 30, 2020 8:52 am     Reply with quote

18LF26K40
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Fri Oct 30, 2020 9:31 am     Reply with quote

I suspect if you look at the assembler, the PIC18 does the read access using
an index register, rather than the NVM registers. The PIC18 there has table
read instructions supporting this. The PIC16 doesn't....
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group