You are showing us the size of the hex file on your development machine's disk, rather than the size of the binary image it represents. It is the latter which must fit in flash memory.
As a hex file is a printable ASCII representation, and has addresses, byte counts, and checksums per line, it is going to be on the order of 2.5-3x the size of the image it represents.
Also, you may not have set your toolchain to strip unused code. For example, in a gcc-based toolchain you would specify --gc-sections
to the linker.
Aesthetically, my favorite architecture in many was is the 14-bit series. The 16-bit PIC18Fxx architecture improves some things, but I find somehow the design less aesthetically pleasing. Which architecture you'll like better probably depends upon your design aesthetic, the extent to which your find yourself wishing things were designed differently, and the extent to which such wishing detracts from your enjoyment working with them.
From a design perspective, there's no particular reason why code addresses and data addresses need to be the same. One thing I like about the 14-bit PICs is that adding a number to an instruction address advances by that many instructions. By contrast, on the PIC18X, each instruction takes two addresses. Consequently, computed jumps using an 8-bit selector are confined to a range of 128 instructions rather than 256. It's a small detail, but having a program counter whose lowest bit is non-functional seems unaesthetic.
Also, the PIC18xx parts add a single-cycle hardware multiply, but unfortunately since it requires one operand to be in W but puts the results in a fixed pair of other registers, it can't be used very effectively for multi-precision operations. If I had my druthers, there would be two types of multiply instructions:
- Simple multiply -- Store W into multiplier register, and store op*W into PRODH:W
- Multply-add --Store PRODH+op*multiplier register into PRODH:W
With such a pattern, a 16x16 operation would be rendered as:
movf OP1L,W
mul OP2L
movwf RESULT0
mula OP2H
movff OP2L,MULTR
mula OP2L
movwf RESULT1
mula OP2H
muvwf RESULT2
movff PRODH,RESULT3
Further, arbitrary-length multiplies could be done with an average cost of a little over two cycles per 8x8 partial product, using the repeated pattern:
mula POSTINC0,c
addwfc POSTINC1,f,c
That pattern would multiply one multi-byte number times an 8-bit value and add the result to another multi-byte number.
As it is, I think the best one can do for an extended multiply is to do the multiply to a destination buffer without doing a built-in add, at a cost of six cycles per 8x8 partial product, and then spend another two-cycles per partial product adding that result to the previous 8xN partial result.
movf multiplier,w
mulwf POSTINC0,c
movf PRODL,w,c
addwfc POSTINC1,w
movff PRODH,INDF1
Four times as long as what could be achieved with a slightly different instruction set. I don't know that I've seen any processor which included a function to compute PRODH+Op1*Op2 but it would be a very simple feature to include in shifter-based multiplies, and it facilitates computing arbitrary product widths with fixed hardware cost. Actually, since the PIC takes four hardware clocks per instruction, the hardware required to allow a 16xN or 32xN multiply would be pretty modest; when computing big products, a 16xN or 32xN multiply with suitable register usage would offer a 2x or 4x speedup.
Best Answer
Of the STM32 (ST Microelectronics) and the Kinetis family (Freescale), I have only worked on the STM32 family of processors and therefore, I will be able to detail my experience with the STM32 and hoping that someone else can do the same for the Kinetis, so you can contrast the two. This list may not be complete, and is simply based on my experience.
PROS:
ST provide a massive set of libraries for each of their processors that you get for free. These libraries contain a massive list of functions required to do most of the basic low level interfacing with the hardware and can make your life a lot simpler.
e.g void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) This initializes the GPIOx peripheral according to the specified parameters in the GPIO_InitStruct.
Simply populate the GPIO structure (and there are example projects to guide you through this process), and call the GPIO_init function. This saves you having to look up atleast 4-5 registers and figuring out what each bit should be.
Their microcontrollers have the Read protect functionality, which can help you protect your IP to some extent, if not completely. There are tons of microcontrollers out there, that don't really do this very well.
They have a family of low power micro-controllers, their L1 series, that have various different levels of power saving features that can be turned on/turned off when required.
Although there are many manufacturers that are now doing their versions of the ARM CM3 cores, ST's F series chips have had a few revisions and although not completely bug free, they are now fairly mature.
Almost all the variants I have worked on have tons of Timers and other peripherals and you can never have enough of those. :)
To get you started, they have some example projects that can be programmed into their evaluation boards, they almost always give you for free. Although I think most other manufacturers would do the same.
CONS:
Although the above mentioned libraries definitely help a lot, however some of the function names are not intuitive and it takes a while to get your head around their naming conventions. This is not true for the entire library, but there is a fair bit of code, that is not well commented, and you will really have to read it to figure out what it is doing.
If you are using their libraries and want to turn on MISRA checking for your project, you will get tons of errors/warnings as their code does not seem to be MISRA compliant. You will need to find a way to exclude their libraries from your MISRA checking. There are ways around this, but they require a bit of work to do so.
ST's documentation for the processors that I have worked on is a bit poor. Their datasheets are not very well written. The information is not in one central/main document. There have what they call a reference manual, tons of application notes and atleast one datasheet. You have to really trawl through these documents sometimes to find the information you are after.
They often describe GPIO ports, and a recommended setting for one of the bits
maybe described 50 pages later.
That is all I can think of at the moment, hopefully this gives you bit of an idea about the STM32 products. I will add more, if I can think of anything else.
A suggestion would be to get an evaluation board for both types of microcontrollers (Kinetis one and an STM32 one), which have the peripherals that you are after, and have a play with them.
That will give you a really good feel for which one suits your needs best.