📜 ⬆️ ⬇️

Safe use of the RESET leg on the Arduino

Picture to attract attention

Hello, dear habravchane!

In this article I will describe how to safely use the RESET leg on the Arduino board for your own needs.

Actually, searching for a solution to this issue led me to a certain lack of legs in the system developed by me (which I hope to describe on Habré, as I finish the implementation) based on the Arduino Pro Mini .
So, the task is clear, and the requirements are:


Attention: the article contains commands, the careless use of which may lead Arduin to an inoperable state.
')
Googling on this issue will put novices in a dead end - it seems they write everywhere that this is impossible, but occasionally it is mentioned that there are ways to get around this restriction, as, for example, here [1] .

So, in order to get the desired result, we need to change the bootloader code, flash it into Arduin and change the fuses! It is in this sequence! It is very important! You are ready?

Step one


Then let's start with the bootloader. In the network you can find many bootloaders for Arduina with various capabilities. I took the smallest - optiboot [2] . It not only frees up an additional 1.5 kilobytes for the main program code, but also allows you to use Watchdog [3] . We download the latest version of the source code ( archive ) from the site, unpack and copy the folder "\ optiboot-9e0c0b9db6fe \ optiboot \ bootloaders \ optiboot" in the folder "pathToArduino \ hardware \ arduino \ avr \ bootloaders \" . I am using Arduino IDE version 1.5.8 . If you have an Arduino IDE version 1.0.5 , then find the bootloaders folder yourself.

Open the file “pathToArduino \ hardware \ arduino \ avr \ bootloaders \ optiboot \ optiboot.c” in a text editor or in an existing programming environment (I use Atmel Studio 6.2 ). The following lines should be commented out:
ch = MCUSR; MCUSR = 0; if (ch & (_BV(WDRF) | _BV(BORF) | _BV(PORF))) appStart(ch); 

And after them insert such code:
  //ch = MCUSR; //MCUSR = 0; //if (ch & (_BV(WDRF) | _BV(BORF) | _BV(PORF))) //appStart(ch); #define PIN_BOOT PCINT14 DDRC &= ~_BV(PIN_BOOT); PORTC |= _BV(PIN_BOOT); _delay_us(4); if(_BV(PIN_BOOT)&PINC) { PORTC &= ~_BV(PIN_BOOT); appStart(MCUSR); } 

Also in the program header, find #include and insert after all the inclusions:
 #include <util/delay.h> 

To verify the correctness of all actions with the bootloader, it is best to create a test firmware, replacing the pointer in the firmware code. Suppose so ( PCINT10 is leg A2 ):
 #define PIN_BOOT PCINT10 
Then on the test firmware, without affecting the fyuzov, you can make sure that we are doing everything correctly.

Let me explain what is happening here. We have removed the transition to the main program, which occurs after a software reset and a low power reset. PCINT14 is the address of our RESET pin in the PORTC register. Using a direct address to the DDRC register , we set pinMode INPUT for this leg and gave it 5 volts through internal resistance (the PORTC register, the so-called pinMode INPUT_PULLUP ). We waited a little while until a sufficient number of electronic engineers flowed through a resistor, and watched the signal on the leg through the PINC register. If there is no signal on the leg, then it is grounded, then proceed to the flashing of the main program. Otherwise, we transfer the leg to the default mode INPUT and run the main program.

Now you have to compile it all. In the omake.bat file, you must replace the path to make.exe . In my case (the Arduino IDE version 1.5.8 ) is “.. \ .. \ .. \ sam \ system \ CMSIS \ Examples \ cmsis_example \ gcc_atmel \ make.exe” . I added a couple more options, so the line to start the compilation looks like this:
 ..\..\..\sam\system\CMSIS\Examples\cmsis_example\gcc_atmel\make.exe OS=windows ENV=arduino LED_DATA_FLASH=1 BAUD_RATE=57600 %* 

First, run omake.exe with the clean parameter, then with the atmega328 parameter and carefully read the answer. If “error:” errors are not mentioned there, then our firmware optiboot_atmega328.hex should appear in the folder. Wonderful!

Step two


Let's start flashing the bootloader. Using the flashing function in the Arduino IDE is not the best option in this case - this will most likely lead to the inoperability of Arduine. For flashing the bootloader, we will use avrdude.exe . This console program is located in the folder "pathToArduino \ hardware \ tools \ avr \ bin \" . Read about the used parameters here [4] . To use it in the folder with the firmware, create one command script flash.bat with the following content:
 ..\..\..\..\tools\avr\bin\avrdude.exe -C "..\..\..\..\tools\avr\etc\avrdude.conf" -c stk500v1 -p m328p -b 19200 -P COM5 %* 

And the second is flash_boot.bat :
 flash.bat -e -U flash:w:optiboot_atmega328.hex:i 

File paths substitute your own. COM port, specify the one used by your SPI programmer or Arduina replacing the programmer. I used another Pro Mini via the PL2303HXA COM programmer . In it, I uploaded a standard ArduinoISP sketch, which emulates the work of the SPI programmer using the STK500 v1 protocol. An approximate wiring diagram is shown in this article [5] .

After everything is connected, you can check the connection with the programmable Arduina by running flash.bat : it will show the microcontroller signature and other information. Now you can run the second script flash_boot.bat . If he says "so many bytes of flash verified" , then everything is OK, the bootloader is in place.

At this step, you can test the test firmware: for example, load standard Blink and, during the launch of the Arduina, ground the test leg ( A2 in this case). There should be an indiscriminate blinking of the built-in LED - this Watchdog restarts the microcontroller at the stage of unsuccessful attempts by the bootloader to read the command from the Serial port to rewrite the main program.

Step Three


Finally, the most crucial stage is the installation of fyuzov. Before you work with them, you should read about them, for example, here [6] .
I want to note that the wrong fusions can be cured with the help of “Atmega fusebit doctor” [7] .

"Atmega fusebit doctor" on bezpechnoy breadboard
"Atmega fusebit doctor" on bezpechnoy breadboard

Using the calculator fyuzov [8] and datashit [9] , create a command script flash_fuse.bat to install the correct fyuzov in our long-suffering chip:
 flash.bat -u -U lfuse:w:0xFF:m -U hfuse:w:0x56:m -U efuse:w:0x05:m 

The number 5 in hfuse is responsible for disabling the RESET function on the corresponding leg. The rest fyuzy at your discretion (check with datashit!). This moment has come, you can still return to the bright side to the standard Arduine, but we will not. After installing fyuzov this team standard ways to change fyyuzy or bootloader will not be! But, if we did everything correctly, then we can sew the main program as usual by grounding the foot RESET (or simply clamping the RESET button on the Arduina board). When you turn on Arduina, the built-in LED will blink erratically - this is a signal to start loading the sketch.

Step Four


Having overcome many difficulties, we compiled the correct bootloader, stitched it into the microcontroller and installed the correct fuses. Now we need to fix something in the file “pathToArduino \ hardware \ arduino \ avr \ boards.txt” so that the Arduino IDE can communicate with our board.

Add your settings to the end of the file (for the Arduino IDE version 1.0.5, they are slightly different):
 ############################################################## pro328o16.name=[Optiboot] Arduino Pro Mini (5V, 16MHz) w/ ATmega328p pro328o16.upload.tool=avrdude pro328o16.upload.protocol=arduino pro328o16.upload.maximum_size=32256 pro328o16.upload.speed=57600 pro328o16.bootloader.tool=avrdude pro328o16.bootloader.low_fuses=0xff pro328o16.bootloader.high_fuses=0x56 pro328o16.bootloader.extended_fuses=0x04 pro328o16.bootloader.file=optiboot/optiboot_atmega328.hex pro328o16.bootloader.unlock_bits=0x3F pro328o16.bootloader.lock_bits=0x0F pro328o16.build.mcu=atmega328p pro328o16.build.f_cpu=16000000L pro328o16.build.board=AVR_PRO pro328o16.build.core=arduino:arduino pro328o16.build.variant=arduino:eightanaloginputs 

The board name “[Optiboot] Arduino Pro Mini (5V, 16MHz) w / ATmega328p” will appear in the Tools / Board menu at the very bottom of the list.

Restrictions


As you remember, the RESET button on the Arduino board closes the RESET leg to the ground [10] . With it, we introduce the microcontroller into the flashing mode of the main program. That is why I do not recommend using this leg in the five volt output mode. If you need to control the "power" load, it is better to bring the ground to the leg, and to start the five volt on the second power supply line. The power is turned off by putting the foot in input mode. So we avoid a possible short circuit. The remaining modes can be used without problems.

The second remark concerns third-party libraries: if we pass a leg as a parameter, then we do not know in which mode it will work. There's nothing to be done. Is that use the leg only on a very simple logic, which we write. And I also recommend pausing at the beginning of the program initialization so that it is clear from the LED that it is better to release the RESET button immediately if the button did not suddenly work as expected.

The third point concerns the standard numbering of the legs. Yes, the RESET leg has no number! There are only microcontroller registers that control it. This problem is easily solved by several revisions of the file “pathToArduino \ hardware \ arduino \ avr \ variants \ standard \ pins_arduino.h” :
 static const uint8_t RST = 20; const uint8_t PROGMEM digital_pin_to_port_PGM[] = { … PC, /* 20 */ }; const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { … _BV(6), /* 20, port C */ }; const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { … NOT_ON_TIMER, /* 20 - port C */ }; 

After that, all standard functions, except analogRead () , will work with the RESET leg number 20 ( RST ), as with any other. And even if you have additional analog legs A6 and A7 , then they work separately according to their principle. You can see this for yourself by writing this sketch:
 void setup() { Serial.begin(9600); pinMode(RST, INPUT_PULLUP); //    RST  HIGH   INPUT } void loop() { Serial.println(digitalRead(RST)); //    RST  1,     Serial.println(analogRead(A6)); //    A6 "" ,    delay(500); } 


Conclusion


I hope that my article will not be for you the only possible way out of the difficult situation in your projects at Arduino. But I will be very happy if she pushes anyone to dig deeper and find interesting solutions.

The archive with all the affected files for Arduino IDE 1.5.8 you can download the link [11] . Directory structure saved.

Comments are accepted in PM or comments.

Useful links:


  1. Few conclusions? Use RESET
  2. optiboot - An optimized bootloader for Arduino platforms
  3. Arduino watchdog or automatic RESET in case of a hang
  4. Russian documentation for AVRDUDE
  5. Arduino Pro Mini Firmware via Nano
  6. Fuse bits are not scary
  7. Fix AVR fuses with Atmega fusebit doctor
  8. AVR fusion calculator
  9. ATmega328P datasheet
  10. Arduino Pro Mini schematic
  11. Archive with all affected files for Arduino IDE 1.5.8

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


All Articles