The at89lp is Atmel’s modern 8051 micro controller family. These mcu’s can fetch one instruction per clock cycle, where the classic 8051 needs 12 cycles. Execution takes 1 to 4 cycles, compared to 12 to 48 for the classic 8051. In the end this makes the new controller 6 to 12 times faster. Alternatively you can run the mcu in ’12 cycle per instruction fetch backwards compatibility’ mode. The choice is made by setting a fuse.
A controller more regularly asked about in the Arduino Microcontrollers forum is the older at89s52 mcu. Actually this is very bare bones micro controller: it has 32 gpio’s, 3 timers, an uart, support for isp and that is about it. It has 256 bytes ram and 8KB flash. Compared to this, the at89lp51ed2 has much more features: spi, i2c, a dac and pwm’s. Besides the 256 bytes internal ram, it has 2KB extended on chip ram and 64KB of flash.
This post is about a modified ArduinoISP version that can program the at89lp family (at least the two members I own: the at89lp4052 and the at89lp51ed2).
At89lp ISP is a bit different from avr ISP in that an extra signal is requiered: slave select (SS). The target is kept in reset as long as th etarget is in in programming mode but during each individual ISP transfer the SS signal has to be pulled down.
This is actually an old project that has been gathering dust in this old branch of my ArduinoISP git hub repo:
I recently picked it up again and back ported (or will do so) some ArduinoISP improvements (e.g. getting rid of the delay in hart beat).
Also I changed the wiring a bit, such that it is compatible with the ‘universal ArduinoISP shield’ described in earlier posts. This wiring should work on all Arduino’s. (Well, actually all avr based Arduino’s. I won’t backport the bitbang spi that allows to run on the arm boards).
Below are some pics:
First an Arduino Mega programming an at89lp51ed2 in a breadboard. Remark the ‘Universial ArduinoISP’ wiring: MISO, MOSI and SCK are obtained from the arduino’s ISP header.
Second, a more tidy setup: a Leonardo fitted with the ‘universal ArduinoISP shield’ programming an at89lp51ed2 sitting in a generic 8051 development board. (Ready to run the knight rider firmware). The extra yellow wire is the extra SS signal. (See also code in the ArduinoISP or at89lp_isp sketches.)
This table lists the connections in a more clear way:
Arduino at89lp ======= ====== MOSI --------- MOSI' (P1.5) (1) MISO --------- MISO' (P1.6) SCK --------- SCK' (P1.7) 10 --------- RESET //--R--|<-LED_HB ------ 9 //--R--|<-LED_ERR ----- 8 //--R--|<-LED_PMODE --- 7 6 --------- SS (p1.4) IOREF(or 5V) --------- VDD ---||---// 100nF GND --------- GND POL ------- VDD P1.3 --LED->|--R--// (2) (1) MOSI', MISO' and SCK' are the 'remapped' SPI signals, they are on different pins than the run time SPI (2) See examples for a remark on connecting the anode of the led to the mcu
The at89lp_isp sketch
I used this sketch to learn about the at89lp isp protocol. I find it still useful:
- As a quick test: it can flash a led blink (on pin P1.3) into the target, read out signature…
- To set the fuses of the at89lp51xx.
When you compile the sketch you can configure building for use with the at89lp4052 or the at89lp51xx chips.
For the latter, you need the
#define AT89LP51. (for the at89lp4052 just put the define in comment).
Compile and upload the sketch to the Arduino and connect to the serial line at 115200 baud. Here is a sample session:
(Tested and compiled with ide 1.6.9.)
Send ‘x’: the sketch will report the target device signature, fuses and lock bits.
Send ‘a’: (at89lp51xx only): this programs suitable fuses.
Send ‘x’ again to read the new fuses.
Send ‘r’: the first 100 bytes from flash memory will be read. This will be all FF’s if it is a new chip.
Send ‘e’: erase chip. if you want to program the flash, this step is needed because you can only turn an ‘1’ into a ‘0’, not the other way round, so you must first set every bit to ‘1’.
Send ‘r’ again: now you definitely should see all FF’s
Press ‘w’: the blink program is now programmed
Press ‘r’ to see if the program is really there.
Press ‘p’ to leave programming mode (‘p’ toggles programming mode).
=> the led should now start blinking.
The ArduinoISP sketch
Compiles with ide 1.6.9.
Supports reading, erasing and writing flash. Reads out signature. For now use the at89lp_isp sketch to set the fuses.
You will need an avrdude.conf file that contains specifications for the at89lp. Get it from the repo: data/avrdude-at89lp.conf
An example command line (linux) that flashes the knight-rider.ihx file to the at89lp51xxx:
avrdude -C avrdude-at89lp.conf -P /dev/ttyACM0 -b 19200 -c stk500v1 -p lp51 -U flash:w:knight-rider.ihx
Tested with avrdude 6.3, but any reasonably recent version should do (say from 6.0.1).
A remark: as always with ArduinoISP you need to make sure auto reset is disabled. For the Leonardo there is noting to do but e.g. the Mega would need a cap between reset and ground to achieve this. In the picture above there is no such cap as I disable auto reset using a modified firmware in the mega’s 16u2 (that is what the blue jumper near the 16u2 is for).
Some 8051 examples…
See examples folder in the repo. They compile with sdcc. Just type ‘make’ to build all samples.
You can configure e.g. the frequency of the crystal you use in hw.h.
This is also the place to configure your target by including the appropriate header: at89lp4052.h or at89lp51x.h
(These headers contain the sfr’s specific for the processor at hand. sfr’s that are standard 8051 are in 8051.h provided by sdcc.)
Here is a quick tour.
Blink. – configurable io
Normally there is not much to say about a blink example. In this case there is. A classic 8051 has “quasi bidirectional io’s” that can be used as input or output without software configuration. The downside is that if you use them as input they are not terribly high impedance and if you use them as output they can’t source a lot of current. To the extent that if you connect a led with its anode side to the io pin and the cathode towards ground (like in the wiring diagram shown above), the io pin can’t source enough current to drive the led. Therefore to blink a led you have to connect the anode to vcc and the cathode towards the io pin, so the microcontroller sinks rather than sources the current.
The at89lp’s ports can be configured as bidirectional, high impedance input, push pull output or, open drain output.
By configuring them as push pull output you can drive a led from the anode side. This is what I did for the blue led in the pictures, using following non generic 8051 code snippet:
/* at89lp specific: configure P1.3 as push pull output */ P1M0 &= ~(1<<3); P1M1 |= (1<<3);
BTW the memory locations for P1M0 and P1M1 are different for the at89lp4052 and the at89lp51x. These addresses are defined in
at89lpx052.h and at89lp51x.h.
For more information on io port configuration, see data sheet.
Always nice. My favorite.
Does not configure the io port as output so led should point towards mcu.
This is actually the Arduino melody sample. It uses tone.c which implements the Arduino tone api.
It illustrates how to register interrupt service routines and the use of the timers.
It outputs a signal on P1.3 that is audible if you wire up some amplifier and speaker to that pin.