![]() |
| 12345.6789 + 9999.99999 packed BCD on 8051 |
Showing posts with label Microcontroller Showdown. Show all posts
Showing posts with label Microcontroller Showdown. Show all posts
Tuesday, November 21, 2017
BCD Addition Speed Test: 6502 vs 8051
Tuesday, May 12, 2015
GCC for STM32F429
About a year ago I bought a Discover kit from ST. This one has an STM32F429, which is an ARM M4 running at 168MHz with 256KB of RAM and 2MB of Flash. This seemed like the beefiest microcontroller I would need for a long time. It also has a 2.4" LCD and an external 64 Mbit SDRAM. At only $24 it seemed like a really good deal.
Last year when I had some free time, I tried to get a blinky program running for the board without much luck. The example I found had a makefile but I could not get make to work with it. For one, it could not find the rm utility to delete files. Since then I have found out that utilities like these can be installed on Windows also.
Next, I tried getting GCC working with Eclipse. For all other microcontrollers I use Code::Blocks, but the tutorials I found used Eclipse. One tutorial had no less than 25 steps to get it working, which is absolutely ridiculous if all you want to do is blink an LED. Good for the author of the blog for being so extensive but I wish ST offered an easy way to get GCC working just to get started. Another option many websites pointed to was Sourcery CodeBench. There is a free version for five different processors but the ARM version is no longer free. Next, I tried OpenSTM32. This is the Eclipse IDE prepackaged with GCC and everything needed to compile. It installed fine but when I tried to update it, the installation failed. Using the old version, I tried to generate a new project using the Standard Peripheral firmware, which for some reason is not included in OpenSTM32. The download for that also failed. Next up was Keil. It seems to work well but I do not like being limited to only 32KB of firmware. App note 230 from Keil shows how to get it working with the STM32F4 Discovery board, which is similar to the board I have. The app note shows how to use the Pack Installer in version 5.10 of the MDK software to download a blinky program or another blinky program based on an RTOS with threads. Unfortunately, the blinky program the entire app note is based on is completely missing from the packages in version 5.14 of MDK. There doesn't seem to be any way to install a simple example without the added complications of an RTOS, which is certainly overkill for blinking LEDs.
What I settled on in the end was a set of GNU ARM Eclipse Plug-ins. There is only one thing to install in Eclipse and the plug-ins generate everything from a wizard. The included blinky program is set to work with the STM32F4 Discovery board, but it compiled and ran fine after I changed the LED pin defines. To upload I used ST-LINK, which is also quirky in that it does not actually use the file you select in the Program window. Instead it uses the last file that was "loaded," so if you select a file then recompile, it will not actually use the new version. This is annoying and took a while to figure out. After I was sure I had things working right, I set Eclipse to upload with ST-LINK automatically after each compile.
To test the new setup, I ran the BCD multiply test from the microcontroller comparison. Since I'm on vacation and don't have all my other stuff, I timed it with a stopwatch and got about 24 seconds. This is five times faster than the LPC1114, which is pretty good. Next, I would like to design an improved version of the 6502 Virtual Trainer with this chip.
Sunday, December 28, 2014
Microcontroller Showdown, Revisited
Back in March I finished the microcontroller comparison of a few chips I was considering using. The 8051 based chips all fared poorly in BCD calculations, which is the main thing they would be used for in another calculator project. Some other 8051 fans pointed out that tests like mine test the compiler more than the chip and the SDCC compiler does a lot less optimizing than GCC. So, I decided to recode the BCD Add routine from the test in assembly. At the beginning I didn't consider this because I thought I would only ever write C for the 8051, but after writing assembly for the 6502, I was excited to try it for the 8051 too.
For this test I used the MCU 8051 IDE simulator. It is really impressive! Being able to see all the RAM and registers helped a lot. It is similar in some ways to what I hoped to accomplish with my 6502 Virtual Trainer. When I translated the original BCD Add function from C, I left out the parts used for subtraction, since they weren't used in the test. Also, some of the values that don't change inside loops are calculated once before the loop and stored for use later. This makes sense because a good C compiler would do this for you. All values are stored in the internal DATA, although this would be far too small for real calculations. The simulator can also work with SDCC, so I was able to simulate the function in C after commenting out the parts for subtraction.
The assembly took a simulated 440us to execute. The C version took between 1365 and 1732us depending on memory model and whether the BCD data was stored in DATA or XDATA. Curiously, storing it in XDATA was always faster. The medium memory model was faster than the large memory model. It seems then that hand-coding the routine in assembly is 3-4 times faster. To be fair, the routines for other architectures might also show a speed up if they were rewritten. Compared to the original numbers of the test, a 3x speedup would make the DS89C450 faster than the MSP430 for this routine. The difference might actually be a little bigger since this test used an upgraded version of SDCC that might optimize better. With that in mind, an 8051-based calculator with external bus (coded in assembly) would outperform an MSP430 with SPI SRAM. That is a bit of a surprise after the results of the first test.
The LPC1114 could also be sped up a little. In the original test the chip was configured to run at 50MHz. Because the flash runs at a maximum 20MHz, 3 wait states are required when executing from flash. However, 3 wait states is a little wasteful since 2.5 would be enough. Running the chip at 40MHz would only require 2 wait states, and would let the flash run at full speed. I'm not sure this would give a whole 16% speedup but I imagine it would offer a little bit of a boost.
For this test I used the MCU 8051 IDE simulator. It is really impressive! Being able to see all the RAM and registers helped a lot. It is similar in some ways to what I hoped to accomplish with my 6502 Virtual Trainer. When I translated the original BCD Add function from C, I left out the parts used for subtraction, since they weren't used in the test. Also, some of the values that don't change inside loops are calculated once before the loop and stored for use later. This makes sense because a good C compiler would do this for you. All values are stored in the internal DATA, although this would be far too small for real calculations. The simulator can also work with SDCC, so I was able to simulate the function in C after commenting out the parts for subtraction.
The assembly took a simulated 440us to execute. The C version took between 1365 and 1732us depending on memory model and whether the BCD data was stored in DATA or XDATA. Curiously, storing it in XDATA was always faster. The medium memory model was faster than the large memory model. It seems then that hand-coding the routine in assembly is 3-4 times faster. To be fair, the routines for other architectures might also show a speed up if they were rewritten. Compared to the original numbers of the test, a 3x speedup would make the DS89C450 faster than the MSP430 for this routine. The difference might actually be a little bigger since this test used an upgraded version of SDCC that might optimize better. With that in mind, an 8051-based calculator with external bus (coded in assembly) would outperform an MSP430 with SPI SRAM. That is a bit of a surprise after the results of the first test.
The LPC1114 could also be sped up a little. In the original test the chip was configured to run at 50MHz. Because the flash runs at a maximum 20MHz, 3 wait states are required when executing from flash. However, 3 wait states is a little wasteful since 2.5 would be enough. Running the chip at 40MHz would only require 2 wait states, and would let the flash run at full speed. I'm not sure this would give a whole 16% speedup but I imagine it would offer a little bit of a boost.
Sunday, March 9, 2014
Microcontroller Showdown, Conclusion
The last chip in the comparison is the Z16F2810. When I started the tests I got a Loop overhead time of only 0.64, which made me think the chip might be very fast. When I moved on to the multiplication and division tests, though, some of them completed in only 0.89 seconds. After looking at the assembly generated during compilation I noticed that the arguments of division were only being copied to the register that holds the answer. It seems that even though all the variables were declared as volatile, the compiler decided to optimize the division out anyway. This made me think the compiler was simply ignoring the volatile keyword but the assembly generated when accessing volatiles is slightly different. Loops involving them take about 25% longer to run, so it does have an effect. The only way I could prevent it from optimizing out multiplies and divides while keeping optimizations was to declare the involved variables globally. The User Manual for the chip helped a lot when looking at this problem and I think it is really well done.
For arithmetic operations, the chip did very well. It was always faster than the MSP430 and almost as fast as the LPC1114 for most things. One place it did very well was division where it outperformed all the other chips by a large margin because it has a hardware divider. General GPIO is also pretty fast, although it does not have any special mechanism for speeding it up like the masks on the LPC1114 or the constant generator on the MSP430. BCD Add was about the same as the MSP430. BCD Multiply was faster than on the MSP430 but still much slower than on the LPC1114.
After running all the chips, here are my conclusions:
Results are after the break.
For arithmetic operations, the chip did very well. It was always faster than the MSP430 and almost as fast as the LPC1114 for most things. One place it did very well was division where it outperformed all the other chips by a large margin because it has a hardware divider. General GPIO is also pretty fast, although it does not have any special mechanism for speeding it up like the masks on the LPC1114 or the constant generator on the MSP430. BCD Add was about the same as the MSP430. BCD Multiply was faster than on the MSP430 but still much slower than on the LPC1114.
After running all the chips, here are my conclusions:
- MSP430 Easy to use and reasonably fast. Good choice for small jobs and low-power projects. Held back by low clock speed (16MHz), small memory, and lack of hardware multiplier.
- LPC1114 The fastest chip by far for everything but division and 8 bit math. Lots of RAM and Flash. Straightforward to use, although there is no real community. Very fast GPIO with masks. Top choice for calculations.
- DS89C450 Fast for 8 bit math, although slow at shifting. Very fast GPIO since each GPIO pin is mapped to its own byte in memory. Extremely slow at BCD calculations. The only real advantage is the external memory bus.
- AT89LP6440 Similar to the DS89C450 but lower clock speed and performance.
- Z16F2810 Good performance but inferior to the LPC1114 in everything but dividing. Debugger is very useful but the IDE itself is sometimes clunky. Enough RAM and very big Flash (128KB). PLCC package is inconvenient.
In the future I plan to do a few more projects that will need the extra horsepower for the LPC1114. For other smaller jobs I will stick with the MSP430.
Monday, March 3, 2014
Microcontroller Showdown, Part 4
The next chip to test is the AT89LP6440. This is a single-cycle 8052 compatible like the DS89C450. It can run from an internal oscillator at 8MHz or an external crystal up to 20MHz like I am using. According to the datasheet, total capacitance for the crystal should not exceed 20pF and the chip itself adds about 10pF of that. The smallest capacitors I can find are 22pF so I ran it without capacitors and it seems to work fine on a breadboard.
As you might imagine, the AT89LP6440 performs similarly to the DS89C450 at 20MHz. The times are not exactly the same, though, because both chips perform some instructions in less cycles than original 8051s. This is apparent, for example, in the multiply times where the AT89LP6440 can do 32 bit multiplication about 30% faster because it does multiplies in 2 cycles instead of the 4 cycles needed by the DS89C450 and standard 8051s. The AT89LP6440 also shifted about 5% faster in the tests, although it was a little slower at BCD calculations. Like the DS89C450, I don't think I will end up using this in a calculator but it may come in handy because it can run at 3 volts and has an external memory interface.
Results are after the break.
As you might imagine, the AT89LP6440 performs similarly to the DS89C450 at 20MHz. The times are not exactly the same, though, because both chips perform some instructions in less cycles than original 8051s. This is apparent, for example, in the multiply times where the AT89LP6440 can do 32 bit multiplication about 30% faster because it does multiplies in 2 cycles instead of the 4 cycles needed by the DS89C450 and standard 8051s. The AT89LP6440 also shifted about 5% faster in the tests, although it was a little slower at BCD calculations. Like the DS89C450, I don't think I will end up using this in a calculator but it may come in handy because it can run at 3 volts and has an external memory interface.
Results are after the break.
Sunday, February 2, 2014
Microcontroller Showdown, Part 3
The next chip I compared was the DS89C450 from Maxim. This is a single-cycle 8051 with clock speeds up to 33MHz. The other single-cycle 8051 I wanted to test is the AT89LP6440 but I wasn't able to program it with an FTDI cable. It expects an SPI interface based on a parallel port and I do not know how to get it working with the FTDI cable.
At first I had a lot of trouble getting the DS89C450 running with the flashing software supplied by Maxim. It just would not connect no matter what crystal or capacitor combination I tried. After a little digging I found out that the baud rate depends on the crystal and that 4800 is the max for 12 and 20MHz crystals. Unfortunately, the flashing software only supports 1200 and 9600 or higher bauds. At 1200 baud I was finally able to connect successfully but the chip returned an error when I tried to load firmware. After more digging it seems the problem is caused by using an FTDI cable instead of a real serial port. I can't really hold this against the manufacturer, though, since the chip and software are over 10 years old at this point. Next I tried connecting over Hyperterminal at 4800 baud and this worked great. The interface for communicating with the chip is actually kind of slick. It gives you a prompt you can type commands into and responds back to your input. Loading firmware at 4800 baud, however, was a real pain. If I decide to seriously use this chip, I will definitely track down a crystal that lets me connect at 57600 baud.
The results of the tests are after the break. I ran them with a 20MHz crystal and scaled the results for what they would probably be with a 33MHz crystal. For compiling I used SDCC. This compiler is new to me but it seems pretty simple to use. In place of -O3 I used --opt-code-speed and for -Os I used --opt-code-size. There wasn't really a difference in the results though. As you can see, it adds 8 bit numbers even faster than the LPC1114, 16 bit numbers about as fast as the MSP430, and 32 bit numbers almost twice as fast. It is also much faster at multiplying than the MSP430, which was a surprise to me. Out of curiosity I looked at the 8051 instruction set and was quite surprised to learn that it has 4-cycle multiplication of 8 bit values. The rest of the instruction set and architecture seems very straightforward and I imagine it would be fun to write assembly code for this chip. Division and shifting are pretty slow. GPIO, however, is very fast. Each pin is mapped to its own byte in memory. This seems like a simple feature and I wish more chips had it. With this the chip can bit bang almost as fast as the LPC1114 can with masks. The real test of the chip, though, is BCD calculations and in this it was pretty disappointing, running 2-3 times slower than the MSP430. For these tests all the data was stored in the on-chip external RAM (xdata). This is slower to access but it was necessary to store it here since the internal RAM holds less than 100 bytes. I also tried storing it in the idata section available in 8052 compatible chips like this but that was even slower. It looks like I won't be using this chip for any calculator designs but I will keep it in case I do a project that needs an external memory interface or memory mapped peripherals.
At first I had a lot of trouble getting the DS89C450 running with the flashing software supplied by Maxim. It just would not connect no matter what crystal or capacitor combination I tried. After a little digging I found out that the baud rate depends on the crystal and that 4800 is the max for 12 and 20MHz crystals. Unfortunately, the flashing software only supports 1200 and 9600 or higher bauds. At 1200 baud I was finally able to connect successfully but the chip returned an error when I tried to load firmware. After more digging it seems the problem is caused by using an FTDI cable instead of a real serial port. I can't really hold this against the manufacturer, though, since the chip and software are over 10 years old at this point. Next I tried connecting over Hyperterminal at 4800 baud and this worked great. The interface for communicating with the chip is actually kind of slick. It gives you a prompt you can type commands into and responds back to your input. Loading firmware at 4800 baud, however, was a real pain. If I decide to seriously use this chip, I will definitely track down a crystal that lets me connect at 57600 baud.
The results of the tests are after the break. I ran them with a 20MHz crystal and scaled the results for what they would probably be with a 33MHz crystal. For compiling I used SDCC. This compiler is new to me but it seems pretty simple to use. In place of -O3 I used --opt-code-speed and for -Os I used --opt-code-size. There wasn't really a difference in the results though. As you can see, it adds 8 bit numbers even faster than the LPC1114, 16 bit numbers about as fast as the MSP430, and 32 bit numbers almost twice as fast. It is also much faster at multiplying than the MSP430, which was a surprise to me. Out of curiosity I looked at the 8051 instruction set and was quite surprised to learn that it has 4-cycle multiplication of 8 bit values. The rest of the instruction set and architecture seems very straightforward and I imagine it would be fun to write assembly code for this chip. Division and shifting are pretty slow. GPIO, however, is very fast. Each pin is mapped to its own byte in memory. This seems like a simple feature and I wish more chips had it. With this the chip can bit bang almost as fast as the LPC1114 can with masks. The real test of the chip, though, is BCD calculations and in this it was pretty disappointing, running 2-3 times slower than the MSP430. For these tests all the data was stored in the on-chip external RAM (xdata). This is slower to access but it was necessary to store it here since the internal RAM holds less than 100 bytes. I also tried storing it in the idata section available in 8052 compatible chips like this but that was even slower. It looks like I won't be using this chip for any calculator designs but I will keep it in case I do a project that needs an external memory interface or memory mapped peripherals.
Wednesday, October 30, 2013
Microcontroller Showdown, Part 2
Here are the results for the tests I did with the MSP430 and the LPC1114. Lately I have been busy with work so I haven't had a chance to do anything with the other three chips. I do have tool chains set up for them and I plan to run the same tests on them soon too.
To time the tests I used an MSP430 LaunchPad which waited for a pulse from the tested chips to begin and end timing. The timer was run from the VLO which is accurate to ±3% so the results are not exact but they give a rough idea of the difference in speed. The tests were done inside two nested loops which iterate altogether 2,400,000 times. Each operation is done once per iteration except adding and GPIO operations which are done 10 times since they should be much faster. At first I did each test 5 times and took the average but then I did them only once since the results were usually very close and some of the later tests took quite a while. To begin with I timed how long the empty loop took then I subtracted that time from the results to get the actual time the operations took. For both chips I used gcc to compile with both -Os and -O3, although there wasn't really a difference except for the BCD routine tests.
As you can see from the table, the LPC1114 was much faster than the MSP430, even running from the bottlenecked flash. The results would be even faster if the tests had been copied to RAM and run from there. I was also surprised to realize that the LPC1114 has a barrel shifter which is very handy. Another neat feature is GPIO masking. Each mask is memory mapped so individuals pins can be toggled with a single write to memory. This allows GPIO operations to be much faster than the traditional load, modify, and store routine.
To time the tests I used an MSP430 LaunchPad which waited for a pulse from the tested chips to begin and end timing. The timer was run from the VLO which is accurate to ±3% so the results are not exact but they give a rough idea of the difference in speed. The tests were done inside two nested loops which iterate altogether 2,400,000 times. Each operation is done once per iteration except adding and GPIO operations which are done 10 times since they should be much faster. At first I did each test 5 times and took the average but then I did them only once since the results were usually very close and some of the later tests took quite a while. To begin with I timed how long the empty loop took then I subtracted that time from the results to get the actual time the operations took. For both chips I used gcc to compile with both -Os and -O3, although there wasn't really a difference except for the BCD routine tests.
As you can see from the table, the LPC1114 was much faster than the MSP430, even running from the bottlenecked flash. The results would be even faster if the tests had been copied to RAM and run from there. I was also surprised to realize that the LPC1114 has a barrel shifter which is very handy. Another neat feature is GPIO masking. Each mask is memory mapped so individuals pins can be toggled with a single write to memory. This allows GPIO operations to be much faster than the traditional load, modify, and store routine.
Monday, September 30, 2013
Microcontroller Showdown, Part 1
Recently I bought some LPC1114 microcontrollers from NXP. They come in DIP packages and feature an ARM Core M0. Although comparing the clock speeds of different architectures is not the best indicator of speed, I would still expect this chip running at 50MHz to be faster than the MSP430s running at 16MHz that I have been using until now. Later I found out that the flash of the LPC1114 only runs at 20MHz, which will bottleneck any programs running from there. Running from RAM would be much faster but the chip only has 4KB of SRAM. On the other hand, it does have a three-stage pipeline. Value-line MSP430s only have instruction-prefetch. All of this makes it a bit difficult to know how much faster one chip would be than another, so I have decided to run a few benchmarks.
Another architecture I have been interested in lately is the 8051. This is much older than the other two architectures I want to check but it remains popular with some people. Instructions take 12, 24, or 48 cycles to execute, which is less efficient compared to an MSP430 which needs only 3-6. Some modern 8051s feature a full-pipeline and clock speeds over 30MHz. These are interesting to me because I think they may be able to outperform the MSP430 in some ways. I was able to sample some AT89LP6440s from Atmel and a DS89C450 from Maxim Integrated which both come in DIP packages. The AT89LP6440 can fetch one byte per clock cycle from memory, meaning that it should in practice run slower than 1 MIPS per MHz but still much faster than other 8051s. It does have a hardware multiplier which surprised me to find out. The datasheet for the DS89C450 lists it as one clock-per-machine cycle, so it should run faster MHz per MHz than the AT89LP6440. It can also run at 33MHz compared to the AT89LP6440 at 20MHz.
The last microcontroller I will test is the Z16F from Zilog. This is a 16-bit CISC design descended from the 8-bit Z80. According to the Zilog website, it outperforms many RISC designs in the same class. It can do 32-bit ALU operations, has a hardware multiplier, and does some pipelining. I know the least about this chip but the design is interesting and I may use it in a future project if it performs well.
Here are some specifications of the microcontrollers that will be involved:
There are many factors that need to be taken into account when choosing a microcontroller. For this test I have decided to test only calculation speed and to ignore other factors such as the peripherals. Consequently, the results will not be relevant to some people. This also will not tell me which microcontroller is the best overall. These particular chips are dissimilar in many ways and this is not a comparison of microcontrollers from the same class. They are only being compared because I am curious about them.
One good reason to do this test is so that I have an excuse to set up the tool chains and programmers for all of these chips. This will take some time so I will release the results in a few parts. It will give me a break from the RPN Scientific Calculator I am making.
Another architecture I have been interested in lately is the 8051. This is much older than the other two architectures I want to check but it remains popular with some people. Instructions take 12, 24, or 48 cycles to execute, which is less efficient compared to an MSP430 which needs only 3-6. Some modern 8051s feature a full-pipeline and clock speeds over 30MHz. These are interesting to me because I think they may be able to outperform the MSP430 in some ways. I was able to sample some AT89LP6440s from Atmel and a DS89C450 from Maxim Integrated which both come in DIP packages. The AT89LP6440 can fetch one byte per clock cycle from memory, meaning that it should in practice run slower than 1 MIPS per MHz but still much faster than other 8051s. It does have a hardware multiplier which surprised me to find out. The datasheet for the DS89C450 lists it as one clock-per-machine cycle, so it should run faster MHz per MHz than the AT89LP6440. It can also run at 33MHz compared to the AT89LP6440 at 20MHz.
The last microcontroller I will test is the Z16F from Zilog. This is a 16-bit CISC design descended from the 8-bit Z80. According to the Zilog website, it outperforms many RISC designs in the same class. It can do 32-bit ALU operations, has a hardware multiplier, and does some pipelining. I know the least about this chip but the design is interesting and I may use it in a future project if it performs well.
Here are some specifications of the microcontrollers that will be involved:
| Microcontroller | Clock Speed | RAM | Flash | Core |
| MSP430G2553 | 16MHz | 0.5KB | 16KB | MSP430 |
| LPC1114FN28 | 50MHz | 4KB | 32KB | ARM Core M0 |
| AT89LP6440 | 20MHz | 4KB | 64KB | 8051 |
| DS89C450 | 33MHz | 1KB | 64KB | 8051 |
| Z16F2810 | 20MHz | 4KB | 128KB | ZNEO |
There are many factors that need to be taken into account when choosing a microcontroller. For this test I have decided to test only calculation speed and to ignore other factors such as the peripherals. Consequently, the results will not be relevant to some people. This also will not tell me which microcontroller is the best overall. These particular chips are dissimilar in many ways and this is not a comparison of microcontrollers from the same class. They are only being compared because I am curious about them.
One good reason to do this test is so that I have an excuse to set up the tool chains and programmers for all of these chips. This will take some time so I will release the results in a few parts. It will give me a break from the RPN Scientific Calculator I am making.
Subscribe to:
Posts (Atom)


