โปรแกรม AVR EEPROM โดยตรงจากแหล่ง C


11

เมื่อคุณรวมรหัสต่อไปนี้ในแหล่ง AVR C คุณสามารถตั้งโปรแกรมฟิวส์ได้โดยตรงโดยไม่ต้องใช้คำสั่งพิเศษหรือไฟล์. hex:

#include <avr/io.h>

FUSES = {
        .low =          LFUSE_DEFAULT ,
        .high =         HFUSE_DEFAULT ,
        .extended =     EFUSE_DEFAULT ,
};

มีกลอุบายที่คล้ายกันกับค่าของโปรแกรมใน EEPROM หรือไม่

ฉันตรวจสอบแล้ว/usr/lib/avr/include/avr/fuse.hว่าฉันสามารถค้นหาความคิดเห็นเกี่ยวกับมาโครได้ที่ไหน แต่ฉันไม่พบความคิดเห็นที่คล้ายกัน/usr/lib/avr/include/avr/eeprom.hและการตีความสิ่งที่ตัวประมวลผลล่วงหน้ามีอยู่ในลีกของฉัน

มันจะมีประโยชน์จริง ๆ ถ้าฉันสามารถรวมค่า EEPROM เริ่มต้นในซอร์สโค้ด C ใครรู้วิธีการทำเช่นนั้น?

Edit1:

เคล็ดลับ FUSES นี้ดำเนินการเฉพาะในเวลา ISP ไม่ใช่เวลา RUN ดังนั้นจึงไม่มีฟิวส์ที่ถูกตั้งโปรแกรมในรหัสแอสเซมบลีที่เป็นผลลัพธ์ในคอนโทรลเลอร์ แต่โปรแกรมเมอร์จะวนไปตามวงจรการเขียนโปรแกรม FUSES พิเศษโดยอัตโนมัติ

edit2:

ฉันใช้เครื่องมือ avr-gcc และ avrdude บน Linux


นี่เป็นเฉพาะเมื่อตั้งโปรแกรม ISP หรือไม่ bootloaders ส่วนใหญ่ไม่อนุญาตให้คุณตั้งโปรแกรมฟิวส์ใช่ไหม
angelatlarge

2
ฉันไม่มีเวลาที่จะเขียนคำตอบแบบเต็มในขณะนี้ แต่อย่างน้อยลองค้นหาคำสั่ง EEMEM นอกจากนี้คุณอาจต้องเปลี่ยนการตั้งค่าลิงเกอร์เพื่อสร้างไฟล์. EPP แยกต่างหากที่โปรแกรมเมอร์จะใช้
PeterJ

@angelat Large การเขียนโปรแกรม ISP เท่านั้น ไม่มี bootloader ในการตั้งค่านี้
jippie

2
โปรดทราบว่าคำตอบของสิ่งนี้ขึ้นอยู่กับว่า toolchain ยินดีที่จะบันทึกในผลลัพธ์ของมันอย่างไร Toolchains ส่วนใหญ่สามารถกำหนดค่าให้สร้างส่วนพิเศษ (หรือใส่ข้อมูลในที่อยู่ที่สมมติขึ้น) ดังนั้นท้ายที่สุดมันจะลงมาที่โปรแกรมเมอร์ไม่สามารถแยกมันออกมาหรือสามารถขับเคลื่อนโดยสคริปต์ที่กำหนดเองซึ่งจะทำเช่นนั้น
Chris Stratton

คำตอบ:


7

ด้วย avr-gcc EEMEMแมโครสามารถใช้กับนิยามของตัวแปรดูlibcเอกสารและตัวอย่างที่นี่ :

#include <avr/eeprom.h>
char myEepromString[] EEMEM = "Hello World!";

ประกาศอาร์เรย์ของอักขระให้อยู่ในส่วนที่ชื่อว่า ".eeprom" ซึ่งหลังจากการคอมไพล์บอกโปรแกรมเมอร์ว่าข้อมูลนี้จะถูกโปรแกรมไปยัง EEPROM ขึ้นอยู่กับซอฟต์แวร์โปรแกรมเมอร์ของคุณคุณอาจต้องระบุชื่อ ".eep" -file ที่สร้างขึ้นในระหว่างกระบวนการสร้างให้กับโปรแกรมเมอร์อย่างชัดเจนหรืออาจพบได้ด้วยตัวเอง


ฉันใช้ชื่อไฟล์ที่แตกต่างกันเล็กน้อยกว่าที่ฉันควรจะเป็น แต่สิ่งเหล่านี้คือคำสั่งที่ฉันรวมไว้ในโปรแกรม EEPROM จากบรรทัดคำสั่ง (และ makefile):
jippie

1
สร้างไฟล์ที่มีข้อมูล Intel Hex ที่โปรแกรมเมอร์ใช้:avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 ihex $(src).elf $(src).eeprom.hex
jippie

1
การเขียนโปรแกรมจริงทำโดย:avrdude -p$(avrType) -c$(programmerType) -P$(programmerDev) -b$(baud) -v -U eeprom:w:$(src).eeprom.hex
jippie

7

ได้คุณสามารถเขียนข้อมูลเริ่มต้นไปที่ EEPROM ด้วยตนเองในซอร์สโค้ด ก่อนอื่นให้อ่านคำแนะนำที่ยอดเยี่ยมนี้เกี่ยวกับ EEPROM ด้วย AVR: คณบดี EEPROM Tutorial ของ AVR นอกจากนี้ฉันควรเพิ่มว่าเป็นความคิดที่ดีกว่าในการสร้างไฟล์ .eep ที่มีข้อมูล EEPROM โดยใช้ makefile ซึ่งจะถูกโปรแกรมไปยังอุปกรณ์พร้อมกับซอร์สโค้ด อย่างไรก็ตามหากคุณไม่คุ้นเคยกับการใช้งาน makefile และ linker ต่าง ๆ คุณสามารถทำได้จากไฟล์ซอร์สโค้ดของคุณ - มันจะเกิดขึ้นทันทีที่วงจรเปิดทำงานซึ่งจะหยุดการทำงานของโปรแกรมเริ่มต้น

ที่จุดเริ่มต้นของโปรแกรม (ก่อนลูปหลักใด ๆ ) คุณสามารถทำสิ่งนี้:

#include <avr/eeprom.h>

#define ADDRESS_1 46  // This could be anything from 0 to the highest EEPROM address
#define ADDRESS_2 52  // This could be anything from 0 to the highest EEPROM address
#define ADDRESS_3 68  // This could be anything from 0 to the highest EEPROM address

uint8_t dataByte1 = 0x7F;  // Data for address 1
uint8_t dataByte2 = 0x33;  // Data for address 2
uint8_t dataByte3 = 0xCE;  // Data for address 3

eeprom_update_byte((uint8_t*)ADDRESS_1, dataByte1);
eeprom_update_byte((uint8_t*)ADDRESS_2, dataByte2);
eeprom_update_byte((uint8_t*)ADDRESS_3, dataByte3);

ฟังก์ชัน "อัพเดต" จะตรวจสอบก่อนเพื่อดูว่ามีค่านั้นอยู่หรือไม่เพื่อบันทึกการเขียนที่ไม่จำเป็นโดยรักษาอายุการใช้งาน EEPROM ไว้ อย่างไรก็ตามการทำเช่นนี้สำหรับสถานที่หลายแห่งอาจใช้เวลาค่อนข้างนาน มันอาจจะดีกว่าที่จะตรวจสอบสถานที่เดียว หากเป็นค่าที่ต้องการสามารถอัปเดตส่วนที่เหลือทั้งหมดได้โดยสมบูรณ์ ตัวอย่างเช่น:

if(eeprom_read_byte((uint8_t*)SOME_LOCATION) != DESIRED_VALUE){
  eeprom_write_byte((uint8_t*)SOME_LOCATION, DESIRED_VALUE);
  eeprom_update_byte((uint8_t*)ADDRESS_1, dataByte1);
  eeprom_update_byte((uint8_t*)ADDRESS_2, dataByte2);
  eeprom_update_byte((uint8_t*)ADDRESS_3, dataByte3);
}

หากคุณกำลังมองหาเพื่อปรับปรุงข้อมูลจำนวนมากให้ลองใช้ฟังก์ชั่นอื่น ๆ eeprom_update_block(...)เช่น และแน่นอนอ่านกวดวิชานั้น มันเขียนได้ดี

คุณสามารถวางคำสั่งการอัพเดท EEPROM ทั้งหมดไว้ในคำสั่งเงื่อนไขตัวประมวลผลเดี่ยว ง่ายมากที่จะทำ:

#if defined _UPDATE_EEPROM_
  #define ADDRESS_1 46  // This could be anything from 0 to the highest EEPROM address
  uint8_t dataByte = 0x7F;  // Data for address 1
  eeprom_update_byte((uint8_t*)ADDRESS_1, dataByte1);
#endif // _UPDATE_EEPROM_

โค้ดนี้จะไม่ถูกคอมไพล์แม้คุณจะทำสิ่งต่อไปนี้:

#define _UPDATE_EEPROM_

คุณสามารถทิ้งสิ่งนี้ไว้เป็นความคิดเห็นและไม่แสดงข้อคิดเห็นหากคุณต้องการเปลี่ยนค่า EEPROM เริ่มต้น สำหรับข้อมูลเพิ่มเติมเกี่ยวกับตัวประมวลผลล่วงหน้า C โปรดดูคู่มือออนไลน์นี้ ฉันคิดว่าคุณอาจสนใจในส่วนต่างๆของมาโครและข้อความแสดงเงื่อนไข


ดูเหมือนว่าคำตอบที่ถูกต้องอยู่ในย่อหน้าสุดท้ายของ PDF ที่เชื่อมโยง Ch. 7 Setting Initial Values.
jippie

ใช่คุณถูกต้อง. ฉันพูดถึงว่าในย่อหน้าแรกของฉัน แต่ไปในกรณีที่คุณไม่คุ้นเคยกับไฟล์ .eep และ linker ใน makefile!
เคิร์ตอี. Clothier

1
การใช้ที่อยู่ EEPROM แบบคงที่นั้นเป็นวิธีปฏิบัติที่ไม่ดี เป็นการดีกว่าที่จะใช้แอตทริบิวต์ EEMEM แทนและให้คอมไพเลอร์จัดการการกระจายที่อยู่ นอกจากนี้ฉันขอแนะนำให้ใช้ / ดำเนินการตรวจสอบ CRC ในแต่ละส่วน หาก CRC ล้มเหลวส่วนที่เกี่ยวข้องประกอบด้วยข้อมูลที่ไม่ได้กำหนดค่าเริ่มต้นหรือข้อมูลเสียหาย ด้วยวิธีนี้คุณสามารถใช้กลไกทางเลือกกับการกำหนดค่าก่อนหน้าในกรณีที่ข้อมูลเสียหาย
Rev1.0

"การใช้ที่อยู่ EEPROM แบบคงที่นั้นเป็นวิธีปฏิบัติที่ไม่ดี" ทำไม?
angelatlarge

1
เมื่อใช้EEMEMตัวแปรคอมไพเลอร์จะดูแลการจัดการกับตัวแปรที่อยู่ใน EEPROM วิธีนี้คุณจะทำงานกับตัวชี้ (คงที่คอมไพเลอร์ที่สร้างขึ้น) ไปยังตัวแปรเมื่อเข้าถึงข้อมูล ในทางกลับกันหากคุณกำหนดที่อยู่ที่ตัวแปรแต่ละตัวอยู่อย่างชัดเจนคุณจะต้องจัดการที่อยู่เหล่านั้นด้วยตัวคุณเองรวมถึงตรวจสอบให้แน่ใจว่าไม่มีตัวแปรที่ใช้ที่อยู่เดียวกันโดยไม่ตั้งใจเขียนทับกัน หรือคำนวณที่อยู่ทั้งหมดอีกครั้งในกรณีที่ขนาดหน่วยเก็บข้อมูลของตัวแปรเปลี่ยนไปในอนาคตเป็นต้น
JimmyB
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.