Multiple Definitions จำกัดความของตัวเชื่อมโยง โปรดดูวิธีแก้ไข Multiple Definitions จำกัดความของ linker
ไลบรารี FlashStorage_samd ซึ่งใช้และแก้ไขจาก FlashStorage ของ Cristian Maglie เป็นวิธีที่สะดวกในการจัดเก็บและดึงข้อมูลของผู้ใช้โดยใช้ Emulated-EEPROM จากหน่วยความจำแฟลชที่ไม่ระเหยของบอร์ด SAMD21/SAMD51
หน่วยความจำแฟลชโดยทั่วไปใช้ในการจัดเก็บรหัสเฟิร์มแวร์สามารถใช้ในการจัดเก็บ / ดึงข้อมูลของผู้ใช้มากขึ้นและเร็วกว่าจาก EEPROM ต้องขอบคุณ การเขียนและการอ่านข้อมูลบัฟเฟอร์ เวลาการเข้าถึงแฟลชจะลดลงอย่างมากเพื่อ เพิ่มอายุการใช้งานของแฟลช
Arduino IDE 1.8.19+ สำหรับ ArduinoArduino SAMD core 1.8.13+ สำหรับ SAMD ARM Cortex-M0+ บอร์ดAdafruit SAMD core 1.7.11+ สำหรับ SAMD ARM Cortex-M0+ และ M4 บอร์ด (Nano 33 IoT ฯลฯ )Seeeduino SAMD core 1.8.3+ สำหรับบอร์ด SAMD21/SAMD51 (Xiao M0, Wio Terminal ฯลฯ )IndustruinoSAMD core 1.0.3+ สำหรับบอร์ด SAMD21 (อุตสาหกรรม DG21 ฯลฯ )IndustruinoSAML core 1.0.0+ สำหรับบอร์ด SAML21 (อุตสาหกรรม 420maker ฯลฯ )Sparkfun SAMD core 1.8.4+ สำหรับบอร์ด SAMD21/SAMD51 (SparkFun_redboard_turbo, SparkFun_Samd51_thing_plus ฯลฯ ) วิธีที่ดีที่สุดและง่ายที่สุดคือใช้ Arduino Library Manager ค้นหา flashstorage_samd จากนั้นเลือก / ติดตั้งเวอร์ชันล่าสุด
อีกวิธีในการติดตั้งคือ:
FlashStorage_SAMD-master.zipFlashStorage_SAMD-masterFlashStorage_SAMD-master ไปยังไดเรกทอรีของ Arduino Libraries เช่น ~/Arduino/libraries/เพื่อให้สามารถรวบรวมได้โดยไม่มีข้อผิดพลาดและตรวจจับและแสดง board_name โดยอัตโนมัติบนบอร์ด Arduino SAMD (Nano-33-Iot ฯลฯ ) คุณต้องคัดลอกไดเรกทอรี ARDUINO SAMD ทั้งหมด _Patches ทั้งหมดลงในไดเรกทอรี Arduino SAMD (~/.Arduino15/แพ็คเกจ
สมมติว่าเวอร์ชัน Arduino SAMD คือ 1.8.13 ตอนนี้จะต้องคัดลอกไฟล์เดียวลงในไดเรกทอรี:
~/.arduino15/packages/arduino/hardware/samd/1.8.13/platform.txtเมื่อใดก็ตามที่ติดตั้งเวอร์ชันใหม่อย่าลืมคัดลอกไฟล์นี้ลงในไดเรกทอรีเวอร์ชันใหม่ ตัวอย่างเช่นเวอร์ชันใหม่คือ x.yy.zz
ไฟล์นี้จะต้องคัดลอกลงในไดเรกทอรี:
~/.arduino15/packages/arduino/hardware/samd/x.yy.zz/platform.txtสมมติว่าเวอร์ชัน Arduino SAMD คือ 1.8.9 ไฟล์เหล่านี้จะต้องถูกคัดลอกลงในไดเรกทอรี:
~/.arduino15/packages/arduino/hardware/samd/1.8.9/platform.txt~/.arduino15/packages/arduino/hardware/samd/1.8.9/cores/arduino/Arduino.hเมื่อใดก็ตามที่ติดตั้งเวอร์ชันใหม่อย่าลืมคัดลอกไฟล์เหล่านี้ลงในไดเรกทอรีเวอร์ชันใหม่ ตัวอย่างเช่นเวอร์ชันใหม่คือ x.yy.z
ไฟล์เหล่านี้จะต้องถูกคัดลอกลงในไดเรกทอรี:
~/.arduino15/packages/arduino/hardware/samd/x.yy.z/platform.txt~/.arduino15/packages/arduino/hardware/samd/x.yy.z/cores/arduino/Arduino.hนี่เป็นข้อบังคับในการแก้ไข ข้อผิดพลาดของคอมไพเลอร์ Arduino SAMD ที่มีชื่อเสียง ดูปรับปรุงความเข้ากันได้ของ Arduino กับ STL (Min และ Max Macro)
...arm-none-eabiincludec++7.2.1bitsstl_algobase.h:243:56: error: macro "min" passed 3 arguments, but takes just 2
min(const _Tp& __a, const _Tp& __b, _Compare __comp)
เมื่อใดก็ตามที่ปัญหาข้อผิดพลาดของคอมไพเลอร์ที่กล่าวถึงข้างต้นได้รับการแก้ไขด้วยการเปิดตัว Arduino SAMD ใหม่คุณไม่จำเป็นต้องคัดลอกไฟล์ Arduino.h อีกต่อไป
เพื่อให้สามารถรวบรวมได้โดยไม่มีข้อผิดพลาดและตรวจจับและแสดง board_name โดยอัตโนมัติบนบอร์ด Adafruit Samd (itsy-bitsy m4 ฯลฯ ) คุณต้องคัดลอกไฟล์ในแพ็คเกจ Adafruit SAMD_Patches ลงในไดเรกทอรี Adafruit SAMD (~/.ArduIno15/แพ็คเกจ
สมมติว่า Adafruit SAMD Core เวอร์ชันคือ 1.7.11 ไฟล์นี้จะต้องคัดลอกลงในไดเรกทอรี:
~/.arduino15/packages/adafruit/hardware/samd/1.7.11/platform.txt~/.arduino15/packages/adafruit/hardware/samd/1.7.11/cores/arduino/Print.h~/.arduino15/packages/adafruit/hardware/samd/1.7.11/cores/arduino/Print.cppเมื่อใดก็ตามที่ติดตั้งเวอร์ชันใหม่อย่าลืมคัดลอกไฟล์นี้ลงในไดเรกทอรีเวอร์ชันใหม่ ตัวอย่างเช่นเวอร์ชันใหม่คือ x.yy.zz ไฟล์นี้จะต้องคัดลอกลงในไดเรกทอรี:
~/.arduino15/packages/adafruit/hardware/samd/x.yy.zz/platform.txt~/.arduino15/packages/adafruit/hardware/samd/x.yy.zz/cores/arduino/Print.h~/.arduino15/packages/adafruit/hardware/samd/x.yy.zz/cores/arduino/Print.cppเพื่อให้สามารถรวบรวมได้โดยไม่มีข้อผิดพลาดและตรวจจับและแสดง board_name โดยอัตโนมัติบนบอร์ด Seeeduino Samd (Xiao M0, Wio Terminal, ฯลฯ ) คุณต้องคัดลอกไฟล์ใน SeeDuino SAMD Packages_Patches ลงในไดเรกทอรี Seeeduino SAMD (~/.Arduino15
สมมติว่ารุ่นหลักของ Seeeduino SAMD คือ 1.8.3 ไฟล์นี้จะต้องคัดลอกลงในไดเรกทอรี:
~/.arduino15/packages/Seeeduino/hardware/samd/1.8.3/platform.txt~/.arduino15/packages/Seeeduino/hardware/samd/1.8.3/cores/arduino/Arduino.h~/.arduino15/packages/Seeeduino/hardware/samd/1.8.3/cores/arduino/Print.h~/.arduino15/packages/Seeeduino/hardware/samd/1.8.3/cores/arduino/Print.cppเมื่อใดก็ตามที่ติดตั้งเวอร์ชันใหม่อย่าลืมคัดลอกไฟล์นี้ลงในไดเรกทอรีเวอร์ชันใหม่ ตัวอย่างเช่นเวอร์ชันใหม่คือ x.yy.zz ไฟล์นี้จะต้องคัดลอกลงในไดเรกทอรี:
~/.arduino15/packages/Seeeduino/hardware/samd/x.yy.zz/platform.txt~/.arduino15/packages/Seeeduino/hardware/samd/x.yy.zz/cores/arduino/Arduino.h~/.arduino15/packages/Seeeduino/hardware/samd/x.yy.zz/cores/arduino/Print.h~/.arduino15/packages/Seeeduino/hardware/samd/x.yy.zz/cores/arduino/Print.cppเพื่อให้สามารถรวบรวมได้โดยไม่มีข้อผิดพลาดและตรวจจับและแสดง board_name โดยอัตโนมัติบน SparkFun Samd (Xiao Sparkfun_redboard_turbo, sparkfun_samd51_thing_plus, ฯลฯ ) บอร์ด คุณต้องคัดลอก SparkFun SAMD/PACKAGES)
สมมติว่า SparkFun SAMD Core เวอร์ชันคือ 1.8.3 ไฟล์นี้จะต้องคัดลอกลงในไดเรกทอรี:
~/.arduino15/packages/SparkFun/hardware/samd/1.8.3/cores/arduino/Print.h~/.arduino15/packages/SparkFun/hardware/samd/1.8.3/cores/arduino/Print.cpp~/.arduino15/packages/SparkFun/hardware/samd/1.8.3/cores/arduino51/Print.h~/.arduino15/packages/SparkFun/hardware/samd/1.8.3/cores/arduino51/Print.cppเมื่อใดก็ตามที่ติดตั้งเวอร์ชันใหม่อย่าลืมคัดลอกไฟล์นี้ลงในไดเรกทอรีเวอร์ชันใหม่ ตัวอย่างเช่นเวอร์ชันใหม่คือ x.yy.zz ไฟล์นี้จะต้องคัดลอกลงในไดเรกทอรี:
~/.arduino15/packages/SparkFun/hardware/samd/x.yy.zz/cores/arduino/Print.h~/.arduino15/packages/SparkFun/hardware/samd/x.yy.zz/cores/arduino/Print.cpp~/.arduino15/packages/SparkFun/hardware/samd/x.yy.zz/cores/arduino51/Print.h~/.arduino15/packages/SparkFun/hardware/samd/x.yy.zz/cores/arduino51/Print.cppMultiple Definitions จำกัดความของตัวเชื่อมโยง การใช้งานไลบรารีปัจจุบันโดยใช้ xyz-Impl.h แทน xyz.cpp มาตรฐานอาจสร้างข้อผิดพลาดที่เชื่อมโยง Multiple Definitions บางอย่างในบางกรณีการใช้งาน
คุณสามารถรวมไฟล์ .hpp นี้ได้
// Can be included as many times as necessary, without `Multiple Definitions` Linker Error
# include " FlashStorage_SAMD.hpp " // https://github.com/khoih-prog/FlashStorage_SAMD ในหลาย ๆ ไฟล์ แต่อย่าลืมใช้ไฟล์ .h ต่อไปนี้ ในไฟล์เพียง 1 .h , .cpp หรือ .ino ซึ่งจะต้อง ไม่รวมอยู่ในไฟล์อื่น Multiple Definitions
// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
# include " FlashStorage_SAMD.h " // https://github.com/khoih-prog/FlashStorage_SAMD ตรวจสอบตัวอย่าง MultifileProject ใหม่สำหรับการสาธิต HOWTO
ดูการอภิปรายในพฤติกรรมที่แตกต่างกันโดยใช้ src_cpp หรือ src_h lib #80
หน่วยความจำแฟลชมีรอบการเขียนจำนวน จำกัด ความทรงจำของแฟลชทั่วไปสามารถดำเนินการประมาณ 10,000 เขียนวัฏจักรไปยังบล็อกแฟลชเดียวกันก่อนที่จะเริ่ม "เสื่อมสภาพ" และเริ่มสูญเสียความสามารถในการเก็บข้อมูล
ดังนั้น ระวัง: การใช้ห้องสมุดนี้อย่างไม่เหมาะสมสามารถทำลายหน่วยความจำแฟลชของไมโครของคุณได้อย่างรวดเร็วและถาวร โดยเฉพาะอย่างยิ่งคุณควรหลีกเลี่ยงการเรียกใช้ฟังก์ชั่น write() บ่อยเกินไปและตรวจสอบให้แน่ใจว่าในชีวิตทั้งหมดของไมโครจำนวนการโทรที่จะ write ดีต่ำกว่าขีด จำกัด ของ 10,000
ต้องใช้ความระมัดระวังแบบเดียวกันหากคุณใช้ EEPROM API Emulation (ดูด้านล่าง) กับฟังก์ชัน EEPROM.commit()
ก่อนอื่นคุณต้องประกาศวัตถุ FlashStorage ทั่วโลกสำหรับแต่ละข้อมูลที่คุณตั้งใจจะจัดเก็บในหน่วยความจำแฟลช
ตัวอย่างเช่นหากคุณต้องการจัดเก็บอายุของบุคคลคุณต้องประกาศ age_storage เช่นนี้:
FlashStorage (age_storage, int ); คำสั่งนี้หมายถึง "สร้าง FlashStorage เพื่อจัดเก็บตัวแปร int และเรียกมันว่า age_storage " ตอนนี้คุณสามารถใช้ age_storage เป็นสถานที่จัดเก็บจำนวนเต็มได้อย่างปลอดภัย:
void readAndStoreUserAge ()
{
Serial. println ( " Please enter your age: " );
String age = Serial. readStringUntil ( ' n ' );
age_storage. write (age. toInt ()); // <-- save the age
}หลังจากรีเซ็ตไมโครคอนโทรลเลอร์เพื่อดึงอายุที่เก็บไว้ที่คุณสามารถใช้ได้:
int user_age = age_storage.read(); รวม FlashStorage_SAMD.h เพื่อรับการจำลอง Eeprom ด้วยหน่วยความจำแฟลชภายใน
ดูตัวอย่าง Emulateeeprom สำหรับตัวอย่าง
API นั้นคล้ายกับ API API Arduino Eeprom API ที่รู้จักกันดี แต่มี 4 ฟังก์ชั่นเพิ่มเติม:
bool isValid() ส่งคืน true ถ้าข้อมูลใน emulated-eEprom นั้นถูกต้อง (ข้อมูลที่เขียนเพื่อแฟลชอย่างน้อยหนึ่งครั้งโดย EEPROM.commit() หรือ EEPROM.put() ) ข้อมูล emulated-eeprom เป็น "ไม่ได้กำหนด" และฟังก์ชั่นส่งคืน falsevoid commit() เก็บข้อมูล EEPROM ใน Flash ใช้สิ่งนี้ด้วยความระมัดระวัง: การโทรทุกครั้งจะเขียนข้อมูลที่สมบูรณ์แบบ-EEPROM เพื่อแฟลช สิ่งนี้จะช่วยลดการเขียนแฟลช-เขียนวารสารที่เหลืออยู่ อย่าเรียกวิธีการนี้ในวงวนหรือคุณจะฆ่าแฟลชของคุณเร็ว ๆ นี้void setCommitASAP(bool value = true) เพื่อตั้งค่าหรือล้างตัวแปรส่วนตัว _commitASAP (ค่าเริ่มต้นเป็น true เพื่อความปลอดภัย) หาก _commitasap เป็นเท็จการเรียกใช้ EEPROM.put() จะไม่บังคับ EEPROM.commit() เพื่อยืดอายุแฟลช คุณจะต้องจำไว้ว่าให้โทร EEPROM.commit() ด้วยตนเองเพื่อบันทึกข้อมูล EMOULD-EEPROM ลงในแฟลชหรือข้อมูลจะหายไปbool getCommitASAP() เพื่อส่งคืนค่าปัจจุบันของ _commitASAPflashstorage_samd/ตัวอย่าง/storenameandsurname/storenameandsurname.ino
บรรทัดที่ 26 ถึง 128 ใน 102e13e
ต่อไปนี้เป็นเอาต์พุตเทอร์มินัลตัวอย่างเมื่อเรียกใช้ตัวอย่าง W5500_BLYNK บน ADAFRUIT SAMD51 ITSYBITSY_M4 โดยใช้ W5500 Ethernet Shield
Start W5500_Blynk on ITSYBITSY_M4
[ 936 ] ChkCrR:CrCCSum= 0xaf50 ,CrRCSum= 0xffffffff
[ 936 ] CCSum= 0x0 ,RCSum= 0x0
[ 936 ] Invalid Stored Dynamic Data. Load default from Sketch
[ 937 ] SaveEEPROM,Sz= 1024 ,DataSz= 0 ,WCSum= 0x1d4d
[ 944 ] CrCCSum= 0x29a6
[ 944 ] MAC:FE-A8- 80 -C6-CE-A3
_pinCS = 0
W5100 init, using SS_PIN_DEFAULT = 10 , new ss_pin = 10 , W5100Class::ss_pin = 1
W5100::init: W5500, SSIZE = 8192
[ 2632 ] IP: 192.168.2.153
[ 2633 ] b:Stay in CfgPortal:No CfgDat
[ 2633 ] CfgIP= 192.168.2.153
F
Your stored Credentials :
MQTT Server = default -mqtt-server
Port = 1883
MQTT UserName = default -mqtt-username
MQTT PWD = default -mqtt-password
Subs Topics = default -mqtt-SubTopic
Pubs Topics = default -mqtt-PubTopic
FFFFF
[ 339285 ] SaveEEPROM,Sz= 1024 ,DataSz= 0 ,WCSum= 0x2e89
[ 339292 ] CrCCSum= 0x219f Save => รีบูต Start W5500_Blynk on ITSYBITSY_M4
[ 1547 ] ChkCrR:CrCCSum= 0x219f ,CrRCSum= 0x219f
[ 1547 ] CCSum= 0x0 ,RCSum= 0x0
[ 1548 ] CrCCSum= 0x219f ,CrRCSum= 0x219f
[ 1548 ] ======= Start Stored Config Data =======
[ 1548 ] Hdr=W5X00,BName=Seeeduino_W5500_BlynkWM
[ 1548 ] Svr=account.duckdns.org,Tok=new_token1
[ 1549 ] Svr1=account.ddns.net,Tok1=new_token2
[ 1549 ] Prt= 8080 ,SIP= 192.168.2.220
[ 1549 ] connectEthernet: Use static_IP= 192.168.2.220
[ 1549 ] MAC:FE-A1-D4-BC- E8 -CB
W5100 init, using SS_PIN_DEFAULT = 10 , new ss_pin = 10 , W5100Class::ss_pin = 1
W5100::init: W5500, SSIZE = 8192
[ 3131 ] IP: 192.168.2.220
[ 3131 ] bg:ECon.TryB
[ 3131 ]
___ __ __
/ _ )/ /_ _____ / /__
/ _ / / // / _ / '_/
/____/_/_, /_ // _/_/_
/___/ v0.6.1 on Arduino Zero
[ 3132 ] BlynkArduinoClient.connect: Connecting to account.duckdns.org: 8080
[ 3244 ] Ready (ping: 6ms).
[ 3311 ] Connected to BlynkServer=account.duckdns.org,Token=new_token1
[ 3311 ] bg:EBCon
Conn2Blynk: server = account.duckdns.org, port = 8080
Token = new_token1, IP = 192.168.2.220
B
Your stored Credentials :
MQTT Server = new -mqtt-server
Port = 1883
MQTT UserName = new -mqtt-username
MQTT PWD = new -mqtt-password
Subs Topics = new -mqtt-SubTopic
Pubs Topics = new -mqtt-PubTopic
BBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBB BBBBBBBBBBStart StoreNameAndSurname on SEEED_XIAO_M0
FlashStorage_SAMD v1 .3.2
EEPROM length: 1024
EEPROM is empty, writing WRITTEN_SIGNATURE and some example data:
Insert your name : John
Insert your surname : Doe
<< Your name: John. Your surname: Doe >> have been saved. Thank you!
You can reset to check emulated-EEPROM data retention.Start StoreNameAndSurname on SEEED_XIAO_M0
FlashStorage_SAMD v1 .3.2
EEPROM length: 1024
Hi John Doe, nice to see you again :-)
Clearing WRITTEN_SIGNATURE for next try
Done clearing signature in emulated EEPROM. You can reset nowStart EEPROM_Clear on SEEED_XIAO_M0
FlashStorage_SAMD v1 .3.2
Emulated EEPROM length (bytes) = 1024
Done clearing emulated EEPROM. Time spent (ms) = 11
Start EEPROM_Clear on SEEED_XIAO_M0
FlashStorage_SAMD v1 .3.2
Emulated EEPROM length (bytes) = 2048
Done clearing emulated EEPROM. Time spent (ms) = 22Start EEPROM_Clear on SEEED_XIAO_M0
FlashStorage_SAMD v1 .3.2
Emulated EEPROM length (bytes) = 4096
Done clearing emulated EEPROM. Time spent (ms) = 42Start EEPROM_get on SEEED_XIAO_M0
FlashStorage_SAMD v1 .3.2
EEPROM length: 1024
EEPROM doesn ' t store valid data, writing WRITTEN_SIGNATURE and some example data
Float written to EEPROM: 123.456
Done writing custom object to EEPROM:
===============
Field1: 3.14159
Field2: 65
Name: Working!
===============
Reset to see how you can retrieve the values by using EEPROM_get! Start EEPROM_get on SEEED_XIAO_M0
FlashStorage_SAMD v1 .3.2
EEPROM length: 1024
EEPROM has valid data with WRITTEN_SIGNATURE. Now read some example data
Read float from EEPROM: 123.456
Read custom object from EEPROM:
===============
Field1: 3.14159
Field2: 65
Name: Working!
=============== ใช่คุณสามารถประกาศ struct ที่มีฟิลด์เพิ่มเติมและเรียก EEPROM.put() เพื่อจัดเก็บโครงสร้างทั้งหมด ดู storenameandsurname สำหรับวิธีการทำ
ใช่ทุกครั้งที่คุณอัปโหลดร่างใหม่เนื้อหาก่อนหน้าของ FlashStorage จะถูกลบ
ไม่ได้หากคณะกรรมการของคุณมีการรวมเข้าด้วยกันขอแนะนำให้ใช้สิ่งนั้นเนื่องจาก EEPROM มีอายุการใช้งานนานขึ้นจำนวนวัฏจักรการเขียน ฯลฯ )
ในกรณีที่ไม่มีตัวตนแบบรวมหรือขนาดเล็กเกินไปสำหรับกรณีการใช้งานของคุณคุณสามารถใช้ไลบรารีนี้เพื่อใช้หน่วยความจำแฟลชส่วนเล็ก
หากคุณได้รับข้อผิดพลาดในการรวบรวมบ่อยกว่านั้นคุณอาจต้องติดตั้ง Core รุ่นใหม่สำหรับบอร์ด Arduino
บางครั้งไลบรารีจะทำงานได้ก็ต่อเมื่อคุณอัปเดตแกนบอร์ดเป็นเวอร์ชันล่าสุดเพราะฉันใช้ฟังก์ชั่นที่เพิ่มขึ้นใหม่
ส่งปัญหาไปยัง: ปัญหา flashstorage_samd
EEPROM.put() และ EEPROM.get() เพื่ออ่าน/เขียนโครงสร้างทั้งหมดใน emulated-eeprommultiple-definitionsSAMD21E1xA , SAMD21G1xA และ SAMD21J1xA![]() Cristian Maglie |
หากคุณต้องการมีส่วนร่วมในโครงการนี้: