PIC32MX Noob in need of some help - Page 1
Forum section: electronics / general

author: MAntunes
author_rank: Regular Contributor
timestamp: October 13, 2017, 06:47:35 pm
content: Hi guys,I recently got the Microstick II from Microchip in order to learn how to program PIC32MX microcontrollers.I have some experience with PIC24F.When I started learning how to program the PIC24F my professor gave me a configuration file that worked beautifully every time but know I'm trying to write my own for the PIC32MX250F128B and I'm having some difficulties.In attachment is my current configuration file. I want the PIC32MX working at 40MHz.The configuration bits that are commented are the ones I don't know how to configure. Could you give some help?Another thing I wanted to ask you is if the SYSTEMConfigPerformance() or SYSTEMConfig() functions are really needed. I want to avoid using the Peripheral Library as I never used I with the PIC24F.Also, if you can point me to some tutorials and examples for this microcontroller I would be very grateful.Thank you in advance,MiguelThank you very much in advance.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: October 13, 2017, 08:54:30 pm
content: Here are settings for 24, 40 and 40MHzCode:#define clockfreq 40#if clockfreq==24#pragma config FPLLMUL = MUL_24, FPLLIDIV = DIV_2, FPLLODIV = DIV_4 //#define clk 1#endif#if clockfreq==40#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_2 //#define clk 1#endif#if clockfreq==48#pragma config FPLLMUL = MUL_24, FPLLIDIV = DIV_2, FPLLODIV = DIV_2//#define clk 1#endif#ifndef clk#error undefined clock#endif#pragma config FWDTEN = ON,WDTPS = PS2048,WINDIS=OFF // 2048=2 secs WDT#pragma config FNOSC = FRCPLL, FPBDIV = DIV_1,FSOSCEN=OFF,FCKSM=CSECME#pragma config JTAGEN = OFF,OSCIOFNC=OFF#pragma config IOL1WAY=OFF,PMDL1WAY=OFF

author: Howardlong
author_rank: Super Contributor
timestamp: October 13, 2017, 09:20:08 pm
content: For PIC32MX2xx and 1xx, there is no wait state requirement or cache, and the peripheral clocks can run at system clock speed, so it’s not unusual to go bare metal.You should be able to get your device up and running with an absolute minimum of code.Code:#pragma config FPLLIDIV = DIV_2 // PLL Input Divider (2x Divider)#pragma config FPLLMUL = MUL_20 // PLL Multiplier (20x Multiplier)#pragma config FPLLODIV = DIV_2 // System PLL Output Clock Divider (PLL Divide by 2)#pragma config FNOSC = FRCPLL // Oscillator Selection Bits (Fast RC Osc with PLL)// 40MHz on pin 10#pragma config OSCIOFNC = ON // CLKO Output Signal Active on the OSCO Pin (Enabled)#pragma config FPBDIV = DIV_1 // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/1)#pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))#pragma config JTAGEN = OFF // JTAG Enable (JTAG Disabled)// Microstick II debug switch position A#pragma config ICESEL = ICS_PGx1 // ICE/ICD Comm Channel Select (Communicate on PGEC1/PGED1)#include <xc.h>#define FCY 40000000void main(void){TRISAbits.TRISA0=0;// 4MHz toggle (5 instruction cycles/phase)while (1){LATAINV=1;}return;}

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: October 13, 2017, 10:47:10 pm
content: Quote from: Howardlong on October 13, 2017, 09:20:08 pmThat's no longer strictly true since introduction of the new 80MHz 32MX174 - with this part you do need to set up flash wait states.This caught me out as I'd not used the bigger MX parts so didn't think to look for anything to do with flash speed.

author: Howardlong
author_rank: Super Contributor
timestamp: October 14, 2017, 02:16:19 am
content: Quote from: mikeselectricstuff on October 13, 2017, 10:47:10 pmGood point, and I was thinking that between writing the email and testing the code above, it promptly dropped out of my FIFO.

author: ggchab
author_rank: Frequent Contributor
timestamp: October 14, 2017, 06:49:47 am
content: Is there any reason for not using the MCC code configurator ? I am learning the dsPIC33EV256GM002 and this seems to be very powerful to create the initialisation code.

author: Howardlong
author_rank: Super Contributor
timestamp: October 14, 2017, 12:20:20 pm
content: Quote from: ggchab on October 14, 2017, 06:49:47 amWhere to start? ;-)I am sure there will be other opinions.I had high hopes for MCC, I used it at the start for a few projects but I lost patience with it, and so here are my issues with MCC...o It's very buggy: do you really want to be trying to debug and patch machine-generated code?o It makes it very difficult to maintain code:---the generated code is not properly segregated from user code;---it's too easy to accidentally wipe your own code when you need to make changes;---the peripheral register bit fields aren't properly documented by the generated code;---maintenance between versions of MCC is very problematic, and there are very frequent releases.o You still need to know at a hardware and register level how each non-complex peripheral works anyway, so MCC is just something extra you have to learn how to use.o You are forced into a directory and file structure dreamt up by the guy who wrote it, it's unlikely to be a structure you'll like.o The generated code for non-complex peripherals is not built for performance, it's built for generic use.o The generated code for non-complex peripherals is over-complicated for most implementations.The only reason I'd use MCC now is for complex peripherals like USB. Everything else I'm bare metal, and use and write my own libraries that are fit for purpose. While you'll apparently be able to get a blinky going from scratch quite quickly (although I bet I'd be able to hand code it quicker), anything with any non-trivial application that needs maintaining, and is built incrementally rather than top-down, will be very difficult.In short, for non-complex peripherals, MCC is merely a crutch that might appear to get you started quickly, but I guarantee that you'll lose patience with it if you're doing anything serious. It is not a replacement for reading a device's data sheet and its errata, in fact it's something extra you have to deal with, I think unnecessarily. If its code quality were better and you could be sure of being able to help you maintain code without it overwriting your own, I might feel better about it!

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: October 14, 2017, 08:06:02 pm
content: Quote from: Howardlong on October 14, 2017, 12:20:20 pmI think the only sensible way to use this sort of thing is to use it as a starting point to get the initial settings, which you then use and tweak as necessary, without going near the tool again.Even then it may create unnecessary stuff or not be quite what you need.After you've taken the generated code and done your own thing with it, the tool can't possibly know what you want to do, so re-generating is very risky.And you can probably pretty much get the same by looking at some example applications.Your time is likely to be better spent understanding the hardware better.

author: ggchab
author_rank: Frequent Contributor
timestamp: October 14, 2017, 08:46:14 pm
content: Thank you for these very interesting tips. This is the first time I program a PIC in C (until now, I used assembler only for PIC 12F, 16F and 18F) and I found the code generated by MCC useful. I will follow your advice and only use it as a starting point.

author: Howardlong
author_rank: Super Contributor
timestamp: October 15, 2017, 10:49:58 am
content: Quote from: ggchab on October 14, 2017, 08:46:14 pmIf you were programming PICs in assembly language before, I can only imagine that MCC will get in your way!

author: ggchab
author_rank: Frequent Contributor
timestamp: October 15, 2017, 12:26:22 pm
content: Yes. As if I was losing the control ...

author: MAntunes
author_rank: Regular Contributor
timestamp: October 16, 2017, 08:55:59 pm
content: Thank you very much.I've been able to make my first program work, a simple LED blinky with a button.I have to read more about the SYSTEMConfigPerformance() function and how it works and do some experiments with and without it. This function does not even come included in the new version of the XC32 compiler so I would like to have my way arround it.I've also started reading the book "Programming 32-bit Microcontrollers in C - Exploring the PIC32" and it seems pretty good.Any more recommendations from you?

author: Howardlong
author_rank: Super Contributor
timestamp: October 16, 2017, 11:30:25 pm
content: The di Jasio book is a bit old now, but it is at least mostly bare metal as I remember it.The Microchip “way” nowadays for PIC32 is Harmony or MCC for the bottom end. Unless you are using USB. Ethernet, or Wifi, I’d ignore these framework/code generators and go bare metal, they just get in your way on any serious project.For USB, for the MX230/250/270 at least, you can still use the legacy MLA, although I am minded to suggest you probably should be going to Harmony nowadays. Be aware that learning Harmony is a significant investment in effort, but then so is the MLA, just in a different way. Myself, I only use Harmony to get access to the complex peripherals like USB and the tcp/ip stack, the rest I do as bare metal.There is no harm in having multiple XC32 verisons and their header/lib files installed either if you require them, they generally don’t interfere with each other in my experience. XC32 as a compiler has been pretty reliable, except for the pro licensing, which continues to occasionally break and frustrate!

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: October 17, 2017, 08:52:03 am
content: Quote from: Howardlong on October 16, 2017, 11:30:25 pmI've used MLA for USB and SD card filesystems & it was pretty simple - I just took one of their demos, stripped out the bits I didn't need and copied the required source files into my project.I think the way they set it up by default is to have your project pull the MLA files from a common MLA folder, but that's pretty stupid as it's bound to break something if it gets updated.

author: JPortici
author_rank: Super Contributor
timestamp: October 17, 2017, 10:46:58 am
content: Quote from: ggchab on October 14, 2017, 06:49:47 amthe only reason one should use MCC is to lay out the pin mapping... (the communication stacks too, that's code you want to "just work")and of course the bigger parts where this is would really be a blessing are not supported.. i had to manually laiy out 141 out of 144 pins of the MU814 (well counting the power pins too) because it's not supported in MCC.dsPICs are simple, just a couple of registers per peripheral and no stupid hardware bugs (like non functional I2C so it has to be done in software)no need to add layers of obfuscation through bloated libraries

author: MAntunes
author_rank: Regular Contributor
timestamp: October 17, 2017, 04:44:32 pm
content: Quote from: mikeselectricstuff on October 13, 2017, 10:47:10 pmSo with my PIC32MX250F128B I don't need to configure any of that?

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: October 17, 2017, 04:45:51 pm
content: Quote from: MAntunes on October 17, 2017, 04:44:32 pmNo. with the right config fuse setting you're ready to go at full speed without touching any oscillator configs.

author: MAntunes
author_rank: Regular Contributor
timestamp: October 18, 2017, 11:52:32 pm
content: Quote from: mikeselectricstuff on October 17, 2017, 04:45:51 pmRight now I'm using the configurations you put gave me.How can I know if it's running at full speed?

author: JPortici
author_rank: Super Contributor
timestamp: October 19, 2017, 04:49:52 am
content: set up a timer so that you have an interrupt every "x" milliseconds and blink a LED. verify it takes "x" millisecondsSet up a PWM module so that it produces a square wave of a certain frequency. measure that frequencyset up the reference clock output to provide a known division of the system clock and measure it

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: October 19, 2017, 07:43:42 am
content: Quote from: MAntunes on October 18, 2017, 11:52:32 pmYou can change the OSCIOFNC setting to send the clock out of a pinOr set up a timer with a known prescale and reload value an output a pin when it rollsOr Set up a UART and check that the output is at the expected baudrateOr Because I said it was known working set of configs...

author: Howardlong
author_rank: Super Contributor
timestamp: October 19, 2017, 07:57:47 am
content: Look at these two lines in my code:Code:// 40MHz on pin 10#pragma config OSCIOFNC = ON // CLKO Output Signal Active on the OSCO Pin (Enabled)I tend to put the clock on the CLKO pin if I can (e.g., not using the pin for a crystal) as a matter of course.Also look at these lines in my code:Code:TRISAbits.TRISA0=0;// 4MHz toggle (5 instruction cycles/phase)while (1){LATAINV=1;}Now you wouldn't leave this in your code, but you can use it as a quick and dirty way to determine if your oscillator is running as expected by probing RA0. This works well for this chip, but be aware that if you have wait states or the peripheral bus isn't running at the system clock frequency, results will be skewed. In the example I gave, the configs have the peripheral bus is running at the system clock frequency and there are no wait states. For higher end PIC32, this likely won't be the case.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: October 19, 2017, 08:31:24 am
content: Quote from: Howardlong on October 19, 2017, 07:57:47 amIt's always a bit dangerous to rely on instruction timings on an unfamiliar chips due to the issues you mention - unless you;re comparing to other chips you don't have a reference for how fast it should be running.Also, it's probably more reliable to do something likeLATAINV=1;LATAINV=1;LATAINV=1;LATAINV=1;in a loop to avoid any confusion caused by how the compiler deals with loops.If you see pulses that are 1/48uS long on a part you expect to be running 48MHz then you know it's right ( thought the opposite is not necessarily true due to possible waitsates, peripheral bus clocks etc.)Timers or other peripherals are more reliable, as long as you understand how their clock source works relative to the CPU.When I started playing with the 80MHz 32MX174 I got really confused as the peripherals were giving the speed I expected but the CPU was runnig exactly 8x slower compared to a '170- turned out this was due to flash waitstates, , which I'd not enountered before as I'd only used the '1x0 devices previously. Definitely something they should highlight in the datasheet!

author: MAntunes
author_rank: Regular Contributor
timestamp: October 19, 2017, 01:44:11 pm
content: Thank you very much!So, with the timers and PWM I can test the peripheral speed, right? And what about the CPU speed? Toggling the GPIO in a loop can tell me the CPU speed?Quote from: mikeselectricstuff on October 19, 2017, 08:31:24 amHow did you work arround this? Using the peripheral library?

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: October 19, 2017, 03:29:32 pm
content: Quote from: MAntunes on October 19, 2017, 01:44:11 pmNo I just read the appropriate part of the datasheet.

author: MAntunes
author_rank: Regular Contributor
timestamp: October 20, 2017, 10:04:02 am
content: Quote from: mikeselectricstuff on October 19, 2017, 03:29:32 pmThank you very much. If I have any questions regarding this I'll ask here.Another question: do I need to define any kind of frequency macro? LikeCode:#define FCY 40000000or something similar or I only need to configure the "fuses" the right way?

author: JPortici
author_rank: Super Contributor
timestamp: October 20, 2017, 10:39:45 am
content: That is required by the compiler's built-in libraries.. e.g. to implement any kind of delay you have to know the frequency you are running at

author: Howardlong
author_rank: Super Contributor
timestamp: October 20, 2017, 10:50:38 pm
content: Quote from: MAntunes on October 20, 2017, 10:04:02 amNot on XC32, sorry that was just me coming straight off a PIC24 project, in XC16 they have a couple of macros that use FCY. It’s still useful to have somewhere clear in your code showing what frequency you think you should be running at, you can use it to derive many things such as baud rates and PWM. Sorry for the confusion, but feel free to use it anyway!

author: MAntunes
author_rank: Regular Contributor
timestamp: October 22, 2017, 03:14:31 pm
content: Thank you very much.So, using the OSCIOFNC bit I was able send the clock to a pin and here is the result:40MHZ on pin10 so I think it's all running fine.Another question I have is about interrupts.Do I need to configure any register to enable interrupts?Code:void __ISR([Vector Number], ipl[Priority Number]) Arbitrary_Function_Name(void){// Do stuff...// Clear interrupt flag}About the handler: I know what to put in the [Vector Number] argument, I just need to search for it in the datasheet. But what about the ipl[Priority Number]? Is it related to the interrupt priority?Would this be an appropriate handler? I can't get it to compile on MPLAB X:Code://I configured the interrupt priority to be 4void __ISR(_TIMER_1_VECTOR,4) _Timer1IntHandler(void){LATAbits.LATA0 ^= 1;IFS0bits.T1IF = 0;}Thanks in advance.EDIT:I've been searching and found the bit for enabling multi vector interrupts (INTCONbits.MVEC). My doubts about the handler are still here, unfortunately.I'll attach my code below.

author: JPortici
author_rank: Super Contributor
timestamp: October 22, 2017, 04:06:00 pm
content: Hi, don't put your config settings in a header file. They should be inside a single *.c source file

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: October 22, 2017, 06:02:00 pm
content: I think there are some examples in the XC32 install dir - there will probably be one for interrupts.The declaration looks like for examplevoid __ISR(_EXTERNAL_4_VECTOR,IPL7SOFT) vsint(void)And the setup :INTCONSET=_INTCON_MVEC_MASK;IFS0CLR=_IFS0_INT4IF_MASK;IPC4bits.INT4IP=7;IEC0bits.INT4IE=1;__builtin_enable_interrupts();To clear int flags you should use IFS0CLR=_IFS0_T1IF_MASK rather than IFSxbits.xxIF=0 to avoid atomicity issues, especially if clearing int flags in the foreground. Not usually an issue but a major PITA to track down when it does bite you.

author: MAntunes
author_rank: Regular Contributor
timestamp: October 22, 2017, 08:17:14 pm
content: Quote from: JPortici on October 22, 2017, 04:06:00 pmWhy? I've always put the config settings in and .h file and all worked fine.Any special reason?Thank you Mike.I've seen that the declaration of the handler function is in the "sys/attribs.h" file.Any way to define it in my configuration file?And what about IPLxSRS vs IPLxSOFT vs IPLxAUTO? What is the diference? I got the following error:Code:Timer_Example.c:50:1: warning: Interrupt priority IPL4 is deprecated. Specify as 'IPL4{AUTO|SOFT|SRS|SAVEALL}' instead. [enabled by default]Quote from: mikeselectricstuff on October 22, 2017, 06:02:00 pmWhat do you mean by atomicity issues?

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: October 22, 2017, 09:11:55 pm
content: SRS is the shadow register set. This speeds up interrupt handling by swapping the context into shadow registers instead of saving on the stack.Unfortunately the SRS is not implemented on the 32MX1/2 devices ( From memory I think it is on the 32MM, and the larger devices), but the header files haven't been designed to warn you if you try to use them on parts where they don't exist - the SRS constant shouldn't be defined in the header files for these partsAtomicity :Using IFSxbits.xxx compiles to a read, mask the flag and write, and therefore non atomic ( interruptable).Consider this situationForeground task uses Timer 1, which it polls for overflow using the T1IF flag.When it sees it set, it does whatever it needs to do, and clears the flag using IFS0bits.T1IF=0;This will compile to something like thistemp=IFS0temp=temp AND NOT <T1 bitmask>IFS0=tempThis will appear to work just fine. Until that rare event of an interrupt whose flag lives in the same IFS register happening in the same machine cycle as the first read.Let's say the Interrupt uses T2IF.FG task reads IFS0 into temp, and at exactly the same time, the T2 interrupt happensIFS0 now T1IF and T2IF set, and this is copied into tempThe next instruction cycle, the interrupt is serviced, which clears T2IF and returns to FG taskThe FG task clears T1IF in temp, but temp also has T2IF still set as it was read before the int happened.FG task rewrites IFS0 with T2IF set, causing a second, spurious T2 interrupt.This spurious T2 interrupt may or may not be a problem, depending on your code.But if it is, and assuming the occurrence is random,and T1 int happens every 10mS, then at 48MHz the probability of it occurring is one in 480,000 T2 interrupts.Needless to say this can result in those "once in a blue moon" type errors that can be a nightmare to track down. Fairly unlikely to happen with just timer events, but when one of the events is asynchronous ( e.g. serial receive) it is quite possible.If the foreground task had used IFS0CLR, which is an atomic, non-interruptable operation, this can't happen.Although it may appear that the interrupt could could safely use a non-atomic operation, it's still a bad idea as at some point you might have a higher priority interrupt, maybe not in this project, but several ones down teh line when you wonder why your old, reliable code has suddenly started misbehaving once every few minutes, hours or days.This was why I needed to rush out and buy a scope in the middle of doing an install in Hong Kong a couple of years ago. I never saw any problems when testing at home, but once we had a big installation of about 10,000 LED nodes, and a random one of them would blink every few seconds.Since then I've always used xxxSET and xxxCLR.There can also be similar issues if you are accessing things like LAT registers in both FG and int codeWhat's annoying is that if the compiler was smarter, it ought to be able to compile xxxbits.xx=0 into the corresponding xxxCLR operation . Unfortunately Microchip seem to be spending all their time on the shit-show that is Harmony.

author: MAntunes
author_rank: Regular Contributor
timestamp: October 23, 2017, 09:34:22 am
content: Thank you Mike. I think I understood it. You've been a great help!Ended up including the "sys/attribs.h" where the interrupt handlers are defined and began using the IFSxCLR for clearing the interrups flags. All worked fine.Quote from: mikeselectricstuff on October 22, 2017, 09:11:55 pmDo you use it for everything or only for handling interrupts?I'll leave my code attached so anyone can see it.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: October 23, 2017, 09:55:51 am
content: Quote from: MAntunes on October 23, 2017, 09:34:22 amAnywhere that there is a SET/CLR register I'd usually use it - that's why it's there. The big risk is that you re-use code where it didn't matter for something where it does.It can make defining things like pins slightly more involved then, e.g. instead ofredled=1you end up withredled_onandredled_offThough I'm sure someone with better C macro-fu could come up with a way to make it nicer

author: Howardlong
author_rank: Super Contributor
timestamp: October 25, 2017, 05:13:08 pm
content: It’d be nice if they’d gone to the trouble of extending the ....bits nomenclature to the set/clr/inv virtual SFRs too.Regarding the (mis)use of, say, IFS0bits.T1IF, for example, the problem is that in unit testing with a single interrupt enabled you’ll be unlikely to see any problem. It’s only when you come to integrating your handiwork, when potentially several interrupts are enabled sharing the same IFS register, that every once in a while your system misbehaves. You might, for example, decide to change from one timer to another, and the problem starts happening, or appears to go away.From experience, it’s incredibly difficult to fathom until you realise where the interaction is.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: October 25, 2017, 08:49:07 pm
content: Quote from: Howardlong on October 25, 2017, 05:13:08 pmIt only needs one int and one FG task updating the same IFSx to potentially be an issue.One thing you do get to recognise with experience , is that ( assuming it doesn't just crash) after a while of observing, you see something happenning very infrequently but with a fairly consistent probability. This generally distinguishes it from things like hardware data errors, which tend to be more more pattern-dependent, bursty or influenced by cable length etc.Once you recognise this low but consistent probability of occurrence , you can start tweaking the frequency of the stimulus to see what makes a difference. The very low probability tells you pretty much immediately it's a "tiny window of vulnerability" type of thing.In the case of the Hong Kong jib, by sending a very high framerate to a very limited number of LED nodes, instead of all of them at a normal rate, I could make it happen often enough to debug in my hotel room on a small piece instead of on-site, at night in the shopping centre.I'd probably have figured it out eventually, but I absolutely had to get it fixed the following night, and knew that by having a scope I could put test pulses out at every possible stage of the code until I'd narrowed it down. I think it was an hour or so round trip to go buy a scope, and half an hour to find the problem.I subsequently had a similar issue (with old recycled code in a new application), and spotted the pattern very quickly purely from the rate of ocurrence.