📜 ⬆️ ⬇️

Ideal development environment for PIC - personal experience

In connection with the innovations on the site, I decided to finally get out of the underground and write something useful. Well, since I program different microcontrollers (MK) and am a fan of Eclipse, I decided to write about it. I will begin with my history of acquaintance with PIC programming, and finish with advice for those who, on duty or because of their enthusiasm, program at the MIC of the PIC family, although, however, these same tips will fit for other MK architectures.

On Wednesday, I got zhelezyachnik in 2006 on the 4th year of study at the university, when I went to work practice at the science and technology center, where, in fact, I still work today. At that time, our company mainstream was using Keil uVision2 for MK based on C51 and ARM. However, I was shoved with simple tasks under the PIC, such as monitoring and controlling a single signal (on-off button), and my first development environment was notepads — paper and computer, plus paper books on PIC. My development environment looked like this:


')
To compile files, I was given an executable of the compiler and a bat-file, which I used completely mindlessly - I don’t even know what the compiler was there. In general, there were harsh times ...

Oh, if someone told me then that there is such a miracle as notepad ++!


Then there was MPASM, but it is poor and I have almost nothing to remember about it. In my opinion, under him I also wrote in the program notepad.

MPLAB IDE


As my skills improved, I learned that instead of a notebook, you can use the coolest, as it seemed to me, MPLAB IDE:



It includes:


Although, if you look at this development environment, its wretchedness and backwardness can frighten off any programmer who has become accustomed to good conditions, but then I didn’t know about it. Help for built-in library functions should be opened separately and look for what, where and how it is called. For beginners - an impossible task. However, in the thematic forums, people still ask which compiler is better to use; someone continues to use MPLAB IDE.

Mikroc


The tasks for the PIC threw up less and less, I began to gain momentum with the development of the C51, ARM7 MK (not to be confused with ARMv7!), Cortex-M. But sometimes they turned to me again for help in writing programs for PIC, and I, out of curiosity, tried new development tools.
By that time, I had been actively programming in Keil uVision3 for a long time - I didn’t want to go back to the antediluvian MBLAB IDE. So I met MikroC, which comes with the PICKit programmers:



The set of buns is almost the same as in MBLAB IDE, but still richer:


Honestly, for small simple projects that make up the main niche of programs under the PIC, this is quite enough. Even beginners can understand normally with help and quickly make working code. Most of our developers who deal with PIC use this environment during development.

Anyway, having made another project in MikroC, I safely forgot about PICs and thought that I would never return to them.

However, the story likes to repeat itself!


After 3 years, in 2013, the task appeared to develop software using a ready-made CD in which the PIC18F4680 was laid. Honestly, I did not even know that among PICs there are such monsters, I always dealt only with trifles!

The tasks were non-trivial - implementation of the loader for in-circuit software update, working in hard real-time mode, working with ADCs, external DACs, control lines, several timers-comparators.

By the way, a little distracted from the topic: only on this project I fully understood what the memory banks in PIC are, how they work and what restrictions they impose on software development. For example, all banks at MK are 256 bytes. And at least kill yourself, but for PIC it is impossible to create a structure that exceeds this 256 bytes in size - the restriction has surfaced when implementing the exchange protocol, but oh well, we drove ...

By this time, Keil uVision3 was already pretty fed up with me, as the complexity of the projects grew and I lacked the functionality available in Keil. Somewhere in 2011, I mastered Eclipse, GCC, the makefile syntax — and started all my projects using these tools. Besides, I already had experience of using the Eclipse + SDCC bundle for the project implementation under C51 MK. After the appearance of Keil uVision4, I installed it, tested it for half an hour and took it down, because it still lags far behind Eclipse in terms of programming convenience.

Eclipse + SDCC


Currently, Eclipse is the de facto standard in software development for embedded systems. Here is a list of Eclipse-based IDEs from popular brands:


Auto substitution, auto-completion tooltips, macros, blackout inactive code areas, easy code navigation and much, much more - I will not list everything - many developers of embedded systems are completely unaccustomed and do not know all these buns that make life much easier:



The main problem of pure Eclipse for developing in C / C ++ under the MK is the difficulty of entering programmers into it, replacing the usual tools that work after installing 1-2 clicks for some plug-ins that require configuration, or, even worse, manually written makefiles - all this requires a significant initial effort to read and study documentation, search for help and manuals for beginners on the Internet. I speak as a person who has experience in transferring a team of software developers to Eclipse.
Only for my development team
If you've read this article - let me know, at least I will find out how the profile hubs are read in Habrahabr

However, in a month, having fully mastered the syntax and once writing a high-quality makefile, all other projects are created using a template and require only minimal customization.

We also had to make a number of additional gestures for setting up projects under the PIC - by default, Eclipse understands the syntax of GCC. Different macros and directives embedded in other compilers (whether CC18 or SDCC) have to be separated at the compilation stage and at the project indexing stage. So that when navigating through the code, the editor does not give false errors to unknown directives, the eclipse-syntax.h file is connected to the project ’s sources :
eclipse-syntax.h
#ifndef ECLIPSE_SYNTAX_H_ #define ECLIPSE_SYNTAX_H_ // keyword SDCC defined when compiling with SDCC compiler #ifndef SDCC #ifdef __SDCC_PIC18F4680 #error "SDCC not found, project compile will be with errors!" #endif // file not parsed through makefile - just for proper eclipse syntax #ifndef __CC18__ #error "__CC18__ not found, use `-D__CC18__` in makefile for proper CC18 compilation!" #define near #define far #define rom #define ram #define _asm #define _endasm #define Nop() #define ClrWdt() #define Sleep() #define Reset() #define clrwdt #define nop #define __code #define __data #define __xdata #define __sfr #define __sbit #define __naked #define __wparam #define __bit char #define __at(num) #else // __CC18__ defined - compile stage! #endif // __CC18__ #define __inline #define __asm #define __endasm #define __interrupt(x) #define INTERRUPT(x) #define USING(x) #define CRITICAL #define CRITICAL_START #define CRITICAL_END #define _REENTRANT #else // if SDCC defined #define INTERRUPT(x) __shadowregs __interrupt (x) //#define USING(x) __using (x) #define USING(x) #define CRITICAL __critical #define CRITICAL_START __critical { #define CRITICAL_END } #endif // SDCC defined #endif /* ECLIPSE_SYNTAX_H_ */ 


In addition, in SDCC, I did not manage to link a large project to a ready-made binary — I also needed to set up GPUtils , which includes gpasm, gpdasm, gplink, and .lkr scripts of MK PIC memory cards. True, because of one bug I found in SDCC at the stage of debugging the code, I eventually returned to the CC18 compiler and linker. Nevertheless, the SDCC and GPUtils were fully configured - for those who suffer, I’ll quote the part of the makefile regarding the options of the running compilers and linkers of CC18, SDCC, GPUtils:
Pieces of makefile
 ########################################################### # project-specific compile options ########################################################### # Project definitions CHIP = 18F4680 DEFINES := -DPIC$(CHIP) #DEFINES += -D__SDCC_PIC$(CHIP) # use SDCC compiler DEFINES += -D__CC18__ # use MPLAB CC18 compiler #DEFINES += -DOPTIMIZE_BITFIELD_POINTER_GET # SDCC memory optimize for bitfield structures ########################################################### # common part for all sdcc-based projects ########################################################### SDCC_BASE = c:/DevTools/SDCC CC = "$(SDCC_BASE)/bin/sdcc.exe" LD = "$(SDCC_BASE)/bin/sdcc.exe" ELF2HEX = "$(SDCC_BASE)/bin/packihx.exe" HEX2BIN = "$(SDCC_BASE)/bin/makebin.exe" ########################################################### # common part for all MPLAB MCC18-based projects ########################################################### MPLAB_BASE = c:/DevTools/CC18 CC_MPLAB = "$(MPLAB_BASE)/bin/mcc18.exe" AS_MPLAB = $(MPLAB_BASE)/mpasm/mpasmwin.exe LD_MPLAB = $(MPLAB_BASE)/bin/mplink.exe ########################################################### # GPUtils used with SDCC for linking project ########################################################### GPUTILS_BASE = c:/DevTools/GNUPICutils GPASM = "$(GPUTILS_BASE)/bin/gpasm.exe" GPDASM = "$(GPUTILS_BASE)/bin/gpdasm.exe" GPLINK = "$(GPUTILS_BASE)/bin/gplink.exe" ########################################################### # C preprocessor flags for MPLAB MCC18 compiler ########################################################### #optimization parameters (default = full optimization) OPT_ENABLE_ALL := -O+ # Enable all optimizations (default) OPT_DEBUG :=-Ou- -Ot- -Ob- -Op- -Or- -Od- -Opa- OPT :=$(OPT_ENABLE_ALL) #OPT :=$(OPT_DEBUG) CFLAGS_MPLAB := -p $(CHIP) CFLAGS_MPLAB += -I $(MPLAB_INC_DIR) CFLAGS_MPLAB += -nw=2066 # suppress Warning [2066] type qualifier mismatch in assignment CFLAGS_MPLAB += -ml # Large memory model CFLAGS_MPLAB += -ls # large stack (can span multiple banks) #CFLAGS_MPLAB += -scs # Enable default static locals #CFLAGS_MPLAB += -sco # Enable default overlay locals (statically allocate activation records). Ignored if set --extended CFLAGS_MPLAB += --extended # generate extended mode code COMPILE_MPLAB_STRING=$(CC_MPLAB) $(CFLAGS_MPLAB) $< -fo=$@ $(DEFINES) $(OPT) AFLAGS_MPLAB := /y AFLAGS_MPLAB += /rDEC # set default radix HEX/DEC/OCT AFLAGS_MPLAB += /l- # disable listing file #AFLAGS_MPLAB += /l$(OBJDIR_MPLAB) # enable listing file AFLAGS_MPLAB += /o # specify path for object files #AFLAGS_MPLAB += /o$(OBJDIR_MPLAB) # specify path for object files #AFLAGS_MPLAB += /q # enable quiet mode AFLAGS_MPLAB += /d__LARGE__ # define symbol AFLAGS_MPLAB += /p$(CHIP) # set processor type #ASSEMBLE_MPLAB_STRING=$(AS_MPLAB) $(AFLAGS_MPLAB) %< # used linker script LDFLAGS_MPLAB := $(CHIP)_g.lkr # objects to compile LDFLAGS_MPLAB += $(OBJS_MPLAB) LDFLAGS_MPLAB += $(MPLAB_LIBS) # specify chip for proper linking LDFLAGS_MPLAB += /p$(CHIP) # verbose mode operation #LDFLAGS_MPLAB += /v # generate report file for stack analysis LDFLAGS_MPLAB += /g # generate .LST file and no .COD file LDFLAGS_MPLAB += /i # do not invoke MP2COD (no .COD or .LST file) LDFLAGS_MPLAB += /w # link MPLAB libs LDFLAGS_MPLAB += /l $(MPLAB_LIB_DIR) # generate MAP file LDFLAGS_MPLAB += /m $(EXEDIR)/$(PROJECT_NAME)_mplab.map # set output file LDFLAGS_MPLAB += /o $(EXEDIR)/$(PROJECT_NAME)_mplab.hex ########################################################### # C preprocessor flags for SDCC v.3.3.0 compiler ########################################################### # ----- processor selection ----- CFLAGS := -m$(ARCH) CFLAGS += -p$(CHIP) # ----- preprocessor options ----- CFLAGS += $(INCS) CFLAGS += $(DEFINES) # ----- verbose & dependancy generate ----- # CFLAGS += -M # generate dependencies # CFLAGS += -E # # CFLAGS += -C # dont discard comments CFLAGS += -c # dont link file (ie have multiple source files) CFLAGS += $(DEBUG) # ----- common settings ----- #CFLAGS += --nostdinc # This will prevent the compiler from passing on the # default include path to the preprocessor. #CFLAGS += --nostdlib # This will prevent the compiler from passing on the # default library path to the linker. #CFLAGS += --less-pedantic # Disable some of the more pedantic warnings. CFLAGS += --stack-auto # All functions in the source file will be compiled as reentrant. # It automatically implies --int-long-reent and --float-reent. CFLAGS += --int-long-reent # Integer (16 bit) and long (32 bit) libraries have been compiled as reentrant. CFLAGS += --float-reent # Floating point library is compiled as reentrant. #CFLAGS += --no-peep #CFLAGS += --funsigned-char # The default signedness for every type will be unsigned. #CFLAGS += --cyclomatic # This option will cause the compiler to generate an information # message for each function in the source file. The message contains # the number of edges and nodes the compiler detected in the # control flow graph of the function, and most importantly # the cyclomatic complexity. # ----- optimization options ----- #CFLAGS += --nogcse # Will not do global subexpression elimination, this option may be used # when the compiler creates undesirably large stack/data spaces to store # compiler temporaries. #CFLAGS += --noinvariant # Will not do loop invariant optimizations. #CFLAGS += --noinduction # Will not do loop induction optimizations. #CFLAGS += --nojtbound # Will not generate boundary condition check when switch statements # are implemented using jumptables. #CFLAGS += --noloopreverse # Will not do loop reversal optimization. #CFLAGS += --nolabelopt # Will not optimize labels (makes the dumpfiles more readable). CFLAGS += --nooverlay # The compiler will not overlay parameters and local variables of any function. CFLAGS += --peep-asm # Pass the inline assembler code through the peep hole optimizer. #CFLAGS += --opt-code-speed # Optimize for code speed rather than size #CFLAGS += --opt-code-size # Optimize for code size rather than speed CFLAGS += --fomit-frame-pointer # Frame pointer will be omitted when the function uses # no local variables. CFLAGS += --use-non-free # Search / include non-free licensed libraries and header files # ----- special options for pic16 port of SDCC ----- CFLAGS += --pstack-model=large # use stack model 'small' (default) or 'large' # don't use extended instruction set - SDCCman, $4.6.20.1 Known Bugs #CFLAGS += -y --extended # enable Extended Instruction Set/Literal Offset Addressing mode #CFLAGS += --pno-banksel # do not generate BANKSEL assembler directives CFLAGS += --obanksel=2 # set banksel optimization level (default=0 no) CFLAGS += --denable-peeps # explicit enable of peepholes CFLAGS += --no-optimize-goto # do NOT use (conditional) BRA instead of GOTO CFLAGS += --optimize-cmp # try to optimize some compares CFLAGS += --optimize-df # thoroughly analyze data flow (memory and time intensive!) #CFLAGS += --preplace-udata-with=udata_shr # Place udata variables at another section: udata_acs, udata_ovr, udata_shr #CFLAGS += --ivt-loc= # Set address of interrupt vector table. #CFLAGS += --nodefaultlibs # do not link default libraries when linking #CFLAGS += --use-crt= # use <crt-o> run-time initialization module #CFLAGS += --no-crt # do not link any default run-time initialization module #CFLAGS += --mplab-comp # enable compatibility mode for MPLAB utilities (MPASM/MPLINK) #CFLAGS += --asm= # Use alternative assembler #CFLAGS += --link= # Use alternative linker CFLAGS += --debug-xtra # show more debug info in assembly output CFLAGS += --debug-ralloc # dump register allocator debug file *.d CFLAGS += --pcode-verbose # dump pcode related info CFLAGS += --calltree # dump call tree in .calltree file #CFLAGS += --gstack # trace stack pointer push/pop to overflow ########################################################### # linker flags ########################################################### #gputils (GNU PIC Utils) used to link objects and libs. GPLINK_FLAGS = -c -m -w -r -I $(LIBDIR) -s $(GPUTILS_BASE)/lkr/$(CHIP)_g.lkr #SDCC linker not used #LDFLAGS := -m$(ARCH) #LDFLAGS += $(DEBUG) #LDFLAGS += --profile #LDFLAGS += --code-size $(FLASH_SIZE) # Code Segment size #LDFLAGS += --code-loc $(FLASH_LOC) # The start location of the code location, default value is 0 #LDFLAGS += --iram-size $(IRAM_SIZE) # Internal Ram size #LDFLAGS += --xram-loc $(XRAM_LOC) # The start location of the external ram, default value is 0 #LDFLAGS += --xram-size $(XRAM_SIZE) # External Ram size #LDFLAGS += --stack-loc $(STACK_LOC) # By default the stack is placed after the data segment. # Using this option the stack can be placed anywhere in the # internal memory space of the 8051. ############################################################################## # MPLAB CC18 compiler - linker $(HEX_MPLAB): $(OBJS_MPLAB) Makefile @echo "--- CC18 Linking objects to $(HEX_MPLAB) ..." @$(LD_MPLAB) $(LDFLAGS_MPLAB) ############################################################################## # SDCC compiler - linker $(HEX): $(OBJS) Makefile @echo "--- SDCC Linking objects to $(HEX) ..." $(GPLINK) $(GPLINK_FLAGS) -o $(HEX) $(OBJS) $(LIBS) $(GPDASM) -p$(CHIP) $(HEX) > $(DASM) 



Epilogue


As you can see, I ended up using the Eclipse bundle with external compilers. Studying compilation options is a necessary and not so difficult task to just give up on it - any programmer will be able to study and use them if necessary. I think, in the end, I got the perfect combination, which is available today for creating projects under the PIC.

Putting together all the development tools, here is a list of compilers that I use in conjunction with Eclipse and get real pleasure from it when programming:

Obviously, if necessary, the list can be easily supplemented.

I hope, having read my story, someone will finally decide for themselves to leave the old IDE and master the new ones.

Dare!

Source: https://habr.com/ru/post/235731/


All Articles