Atmel Studio- ATmega128 bootloader - avr

I am trying to write a customized boot-loader for ATmega AVR's. I write a code, and it work perfectly in small AVR's like ATmega32A and ATmega8A. But when i want to use it in ATmega128A, it writes nothing in flash segment.
I'm sure Fuses are correct, ATmega103 mode is disabled, and the program starts at boot section, but it does nothing..
Before calling function "boot_program_page" I set PORTC and turn some LED's on, and after that I cleared PORTC and LED's goes off. so the code in executing completely too.
The function I am using is an example provided in avr/boot.h.
It should write some data ( 0x00 actually ) in page 0 of flash memory..
here is my code :
#define F_CPU 8000000UL
#include <inttypes.h>
#include <avr/io.h>
#include <avr/boot.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
void boot_program_page (uint32_t page, uint8_t *buf);
int main(void)
{
uint8_t data[SPM_PAGESIZE] = {0};
uint32_t page = 0;
DDRC = 255;
PORTC = 255;
page *= (uint32_t)SPM_PAGESIZE;
boot_program_page(page,data);
_delay_ms(1000);
PORTC = 0;
while (1)
{
}
}
void boot_program_page (uint32_t page, uint8_t *buf)
{
uint16_t i;
uint8_t sreg;
// Disable interrupts.
sreg = SREG;
cli();
eeprom_busy_wait ();
boot_page_erase (page);
boot_spm_busy_wait (); // Wait until the memory is erased.
for (i=0; i<SPM_PAGESIZE; i+=2)
{
// Set up little-endian word.
uint16_t w = *buf++;
w += (*buf++) << 8;
boot_page_fill (page + i, w);
}
boot_page_write (page); // Store buffer in flash page.
boot_spm_busy_wait(); // Wait until the memory is written.
// Reenable RWW-section again. We need this if we want to jump back
// to the application after bootloading.
boot_rww_enable ();
// Re-enable interrupts (if they were ever enabled).
SREG = sreg;
}

Related

How to code for DHT11, pH Sensor with i2c 16x2 LCD in Arduino Uno?

I'm working on my college project on which I have to measure the temperature show it on 16x2 LCD and also to switch the cooling device according to the temperature, also I have to use pH Sensor and have to display its value on 16x2. Currently I'm using the code below for Temperature and switching, but it is not working properly. It shows the temperature on the screen but also some garbage value, and also not switching properly.
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <dht.h>
dht DHT;
#define DHT11_PIN 7
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7);
const int ledPin = 6;
void setup()
{
lcd.setBacklightPin(3,POSITIVE);
lcd.setBacklight(HIGH);
lcd.begin(16, 2);
lcd.clear();
Serial.begin(9600);
for (int DigitalPin = 8; DigitalPin <= 8; DigitalPin++) {
pinMode(DigitalPin, OUTPUT);
}
}
void loop()
{
int chk = DHT.read11(DHT11_PIN);
float temp=(DHT.temperature);
float Hum=(DHT.humidity);
lcd.print("Temp C ");
lcd.setCursor(6,0);
lcd.print(temp);
lcd.setCursor(0,1);
lcd.println("Humid % ");
lcd.setCursor(6,1);
lcd.print(Hum);
delay(1000);
if (temp <= 29)
digitalWrite(8, LOW);
else if (temp>30)
digitalWrite(8, HIGH);
}
I will divide my answer into two parts:
Hardware:
Please describe your hardware configuration in order to narrow down your problem: How are you switching the relay? Is it optically coupled? Are you using a transistor? If so, what type? Does your relay have reverse diode protection? (Do not connect your relay directly to an Arduino pin)
Code
2.1. This for-loop in your setup() is incorrect:
for (int DigitalPin = 8; DigitalPin <= 8; DigitalPin++) {
pinMode(DigitalPin, OUTPUT);
}
You are indexing from 8 to 8, hence you don't need a for loop to declare a single pin as an output.
2.2. In general, you can assign your output pins to variables, or as a macro like you did for the DHT. Just be consistent. Additionally, your code needs general tidying up:
a . Start your code with all libraries calling
#include <Wire.h> // The Wire.h library is already called by the LiquidCrystal_I2C library, so you don't need to call it if you use the I2C one
#include <LCD.h> // You are using the LCD library...
#include <LiquidCrystal_I2C.h> // but also the I2C lcd library. You don't need both.
#include <dht.h> // Is this the latest version? Use Adafruit's
b. Try to group all your macros at the beginning. Declare pins or constants here:
// Using macros
#define DHT11_PIN 7
#define DigitalPin 8
#define DHT11_PIN 7
or using constants for pins. Choose one, not both:
// Group all your const int together, for the sake of clarity
const int DHT_PIN = 7;
const int DigitalPin = 8;
const int ledPin = 6;
c. I believe this constructor is not correct for the library you chose. Check the example from this library (assuming it is the same, which I believe it is)
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7);
try with this constructor, instead:
// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);
d. The setup() function needs some changes too:
void setup()
{
// You don't seem to be using the serial library. However, if you use it, it is
// preferable to start it first.
Serial.begin(9600);
// LCD configuration
lcd.begin(16, 2); // Always call the begin() method first
lcd.setBacklightPin(3,POSITIVE); // Then, use additional configuration methods.
lcd.setBacklight(HIGH);
lcd.clear();
// Once again, please check if you are using the right library.
// It might be the cause of the garbage you see.
// Initialize the type of pin
pinMode(DigitalPin, OUTPUT);
}
e. According to Adafruit's library (please see the examples), you are missing a Macro to declare the type of DHT sensor you are using:
#define DHTTYPE DHT11
f. In your main loop() you are reading values with some strange parenthesis:
int chk = DHT.read11(DHT11_PIN);
float temp=(DHT.temperature);
float Hum=(DHT.humidity);
which, according to the latest library, should be:
// The latest library does not have this prototype: int chk = DHT.read11(DHT11_PIN); What is it for in your dht lib?
float temp = DHT.readTemperature(); // instead of: float temp=(DHT.temperature); --> which should be DHT.temperature(); in any case
float hum = DHT.readHumidity(); // instead of: float Hum=(DHT.humidity);
TL;DR: Share your hardware in order to assist you. Update your libraries, clean-up your code, and use the right methods from the latest libraries.
Thankyou so much for your guidance, below is the working code for me:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#define DHTPIN 7 //digital pin for sensor
#define DHTTYPE DHT11 // DHT 11
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
void setup()
{
pinMode(8, OUTPUT); //for configuring relay output
lcd.begin(16, 2);
dht.begin();
}
void loop() {
delay(1000);
float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
float f = dht.readTemperature(true);
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t) || isnan(f))
{
lcd.print("NO CONNECTION");
return;
}
//Hum code
lcd.setCursor(0, 0);
lcd.print("Hum:");
lcd.print(h);
lcd.print(" % ");
//Temp code
lcd.setCursor(0, 1);
lcd.print("Temp:");
lcd.print(t);
lcd.print(" C");
//To operate relay
{
if (t <= 26)
digitalWrite(8, LOW);
else if (t>27)
digitalWrite(8, HIGH);
}
}

Pulse width modulation (PWM) on Attiny 9

I am using an Attiny 9.
I connected a LED to PB1.
I wrote following code and upload it to the Attiny 9.
#define F_CPU 800000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/sleep.h>
#include <avr/power.h>
#define D0 PB1
int main(void)
{
power_adc_disable();
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
TCCR0A |= (1<<WGM00)|(1<<WGM01)|(1<<COM0B1);
TCCR0B |= (1<<WGM03)|(1<<WGM02)|(1<<CS00);
DDRB |= 1<<D0;
PORTB |= 1<<D0;
_delay_ms(3000);
PORTB &= ~(1<<D0);
for (uint8_t i = 255; 247 < i; --i)
{
OCR0B = i;
_delay_ms(70);
}
for (uint8_t i= 247; -1 < i; --i)
{
OCR0B = i;
_delay_ms(4);
}
while(1){
sleep_enable();
sleep_cpu();
}
return 0;
}
I want the LED to be lighten and darken. But after I uploaded the code, the LED illuminates continuously. I also read a datasheet of Attiny 9. I followed how to use PWM. But it's not working.
What's wrong?
There are a number of issues with that code.
You're putting the processor in to power down mode, which according to the datasheet, disables the clocks and only asynchronous events can take place.
You're setting it to use fast PWM mode with OCR0A as your top, but you aren't setting OCR0A anywhere. You won't generate any compare matches if you your timer can't count high enough. It would appear from your loops that you are expecting the timer to count to 255.
You only change the duty cycle of the PWM before your while loop, so even if your PWM gets set up correctly, you won't ever be able to see your LED pulse like you want.
Here's a link giving an example of how to set up a PWM and change its duty cycles:
http://allaboutavr.com/index.php/2017/05/13/chapter-5-timers-and-pwm-pulse-width-modulation/
Ty something like this:
#include <avr/io.h>
#include <util/delay.h>
#define D0 PB1
int main(void)
{
DDRB |= 1<<D0;
TCCR0A |= (1<<WGM00)|(1<<COM0B1);
TCCR0B |= (1<<WGM02)|(1<<CS00);
while (1) {
for (uint8_t i = 0; i < 255; i++) {
OCR0B = i;
_delay_ms(4);
}
for (uint8_t i = 255; i >= 0; i--) {
OCR0B = i;
_delay_ms(4);
}
}
}

__seg_fs on GCC. Is it possible to emulate it just in a program?

I've just read about support for %fs and %gs segment prefixes on the Intel platforms in GCC.
It was mentioned that "The way you obtain %gs-based pointers, or control the
value of %gs itself, is out of the scope of gcc;"
I'm looking for a way when I manually can set the value of %fs (I'm on IA32, RH Linux) and work with it. When I just set %fs=%ds the test below works fine and this is expected. But I cannot change the test in order to have another value of %fs and do not get a segmentation fault. I start thinking that changing the value of %fs is not the only thing to do. So I'm looking for an advice how to make a part of memory addressed by %fs that is not equal to DS.
#include <stddef.h>
typedef char __seg_fs fs_ptr;
fs_ptr p[] = {'h','e','l','l','o','\0'};
void fs_puts(fs_ptr *s)
{
char buf[100];
buf[0] = s[0];
buf[1] = s[1];
buf[2] = s[2];
buf[3] = '\0';
puts(buf);
}
void __attribute__((constructor)) set_fs()
{
__asm__("mov %ds, %bx\n\t"
"add $0, %bx\n\t" //<---- if fs=ds then the program executes as expected. If not $0 here, then segmentation fault happens.
"mov %bx, %fs\n\t");
}
int main()
{
fs_puts(p);
return 0;
}
I've talked with Armin who implemented __seg_gs/__seg_fs in GCC (Thanks Armin!).
So basically I cannot use these keywords for globals. The aim of introducing __seg_gs/fs was to have a possibility to dynamically allocate regions of memory that are thread-local.
We cannot use __thread for a pointer and to allocate a memory for it using malloc. But __seg_gs/fs introduce such possibility.
The test below somehow illustrates that.
Note that arch_prctl() was used. It exists as 64-bit version only.
Also note that %fs is used for __thread on 64-bit and %gs is free.
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <asm/ldt.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <asm/prctl.h>
#include <sys/syscall.h>
#include <unistd.h>
typedef __seg_gs char gs_str;
void gs_puts(gs_str *ptr)
{
int i;
char buf[100];
for(i = 0; i < 100; i++)
buf[i] = ptr[i];
puts(buf);
}
int main()
{
int i;
void *buffer = malloc(100 * sizeof(char));
arch_prctl(ARCH_SET_GS, buffer);
gs_str *gsobj = (gs_str *)0;
for (i = 0; i < 100; i++)
gsobj[i] = 'a'; /* in the %gs space */
gs_puts(gsobj);
return 0;
}

ATMega2560 PCINT Interrupts

i am new to Atmel, so maybe the question is quite simple.
I have the following situation:
I have an ATMega2560 and want to get Interrupts on the Pins PK0-PK7. I am interested in the PIN Change from Low to HIGH. (I have connected one photocell to every PIN)
I have read that the interrupt for PCINT[0-2] are fired everytime (pin high and pin low) so i defined an array to ignore the PIN DOWN Interrupt.
So i have the following code:
Note: I do not understand, why i need to set DDRC as input and not DDRK ?
#define HIGH 1
#define LOW 0
volatile uint8_t portbhistory = 0xFF;
uint8_t pinState[8];
void initSystem()
{
int i;
for(i = 0; i < sizeof(pinState) / sizeof(*pinState); i++)
{
pinState[8] = 0;
}
DDRB = 0xff; // set Port B as output
DDRC = 0; // WHY DDRC ?? PCINT == PK0-7, so DDRK ? // all Pins input
PORTC = 0xff; // same question ... // turn on pullup for every pin
PCICR |= _BV(PCIE2); // enable interrupt for PCIE2
PCMSK2 = 0xff; // Interrupt at all pins
sei(); // turn on interrupts
}
int main(void)
{
initSystem();
while(1)
{
}
}
ISR(PCINT2_vect)
{
int i;
uint8_t changedbits;
changedbits = PINC ^ portbhistory;
portbhistory = PINC;
/*
if(pinState[changedbits] == HIGH)
{
pinState[changedbits] = LOW;
return;
} else
{
pinState[changedbits] = HIGH;
}
*/
setDebugLED(1);
_delay_ms(30);
setDebugLED(0);
}
If i connect 5V to one of the PINS (PK0-7) the LED flashes instantly. But if i disconnect the 5V it takes ~2seconds for the LED to flash again. In this time the one pin i connected 5V before does not let the LED flash again if i connect the 5 V again.
Other Ports work in this time.
So you could say, that the PIN HIGH interrupt for all pins work fine and get fired instantly but the PIN LOW interrupts need some time (~2sec.) In this time the port is "disabled" or somethig.
Can anyone help me with that?
EDIT
Just some wrong edit ...
EDIT 2
So, i totally forgot to post my solution here. sorry for that!
The solution is: My external circuit pulls the PIN to Ground or to 5V.
Thank you!

Smallest (code-wise) bit - banged serial interface on PIC10

I need to interface to a PIC10 micro with some serial interface. Since these small devices lack hardware support for SPI I2C and UART a Software solution is inevitable.
However, since I need to preserve as much of the Programm memory to store (static) configuration and identify information to be retrieved via said interface, what would probably be the smallest solution?
I will need to program this in ASM since there seems no good C compiler for PIC10. However, this will be my first real encounter with ASM to speak of.
Try this download which contains code samples and says:
"Listed below are five PIC UART software routines to use with PIC microprocessors that have no hardware UART"
Link rot has broken the original link try this link.
In my opinion the xc8 compiler works pretty well, also for the PIC10.
Here is an example in C:
#include <xc.h>
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 4000000
#endif
#define Baudrate 1200 //bps
#define OneBitDelay (1000000/Baudrate)
#define DataBitCount 8 // no parity, no flow control
#define UART_RX RA1 // UART RX pin
#define UART_TX RA0 // UART TX pin
#define UART_RX_DIR TRISA1 // UART RX pin direction register
#define UART_TX_DIR TRISA0 // UART TX pin direction register
//Function Declarations
void InitSoftUART(void);
unsigned char UART_Receive(void);
void UART_Transmit(const char);
__CONFIG(FOSC_INTOSC & MCLRE_OFF & WDTE_OFF & LVP_OFF & CP_OFF &
WRT_OFF & PWRTE_OFF & WRT_OFF & BOREN_ON & LPBOR_ON & BORV_LO);
void main()
{
unsigned char ch = 0;
ANSELA = 0x00; // Set ports as digital I/O, not analog input
ADCON = 0x00; // Shut off the A/D Converter
FVRCON = 0x00; // Shut off the Voltage Reference
PORTA = 0x00; // Make all pins 0
InitSoftUART(); // Intialize Soft UART
InitSoftUART(); // Intialize Soft UART
while(1)
{
ch = UART_Receive(); // Receive a character from UART
UART_Transmit(ch); // Echo back that character
}
}
void InitSoftUART(void) // Initialize UART pins to proper values
{
UART_TX = 1; // TX pin is high in idle state
UART_RX_DIR = 1; // Input
UART_TX_DIR = 0; // Output
}
unsigned char UART_Receive(void)
{
// Pin Configurations
// GP1 is UART RX Pin
unsigned char DataValue = 0;
//wait for start bit
while(UART_RX==1);
__delay_us(OneBitDelay);
__delay_us(OneBitDelay/2); // Take sample value in the mid of bit duration
for ( unsigned char i = 0; i < DataBitCount; i++ )
{
if ( UART_RX == 1 ) //if received bit is high
{
DataValue += (1<<i);
}
__delay_us(OneBitDelay);
}
// Check for stop bit
if ( UART_RX == 1 ) //Stop bit should be high
{
__delay_us(OneBitDelay/2);
return DataValue;
}
else //some error occurred !
{
__delay_us(OneBitDelay/2);
return 0x000;
}
}
void UART_Transmit(const char DataValue)
{
/* Basic Logic
TX pin is usually high. A high to low bit is the starting bit and
a low to high bit is the ending bit. No parity bit. No flow control.
BitCount is the number of bits to transmit. Data is transmitted LSB first.
*/
// Send Start Bit
UART_TX = 0;
__delay_us(OneBitDelay);
for ( unsigned char i = 0; i < DataBitCount; i++ )
{
//Set Data pin according to the DataValue
if( ((DataValue>>i)&0x1) == 0x1 ) //if Bit is high
{
UART_TX = 1;
}
else //if Bit is low
{
UART_TX = 0;
}
__delay_us(OneBitDelay);
}
//Send Stop Bit
UART_TX = 1;
__delay_us(OneBitDelay);
}
Source for this code is the :Microchip forum

Resources