PIC32 vs dsPIC กับ ARM vs AVR สถาปัตยกรรมนั้นสำคัญหรือไม่เมื่อเราทำการเขียนโปรแกรมในภาษา C [ปิด]


10

ขณะนี้เรากำลังใช้ไมโครคอนโทรลเลอร์ PIC32 แบบ 32 บิต มันใช้งานได้ดีสำหรับความต้องการของเรา แต่เรากำลังสำรวจไมโครคอนโทรเลอร์คนอื่น ๆ ที่สามารถทำให้เราดีขึ้น + เรามีโครงการอื่นที่เรากำลังเลือก MCU เพื่อจุดประสงค์นั้นเราได้เลือกไมโครคอนโทรลเลอร์SAM DA ที่ใช้ ARMซึ่งเป็น 32- บิตเหมือนกัน แต่ใช้ ARM (เป็นที่นิยมมากกว่า PIC32 - ฉลาดในอุตสาหกรรม)

ตอนนี้สำหรับ PIC32 เราใช้ MPLAB แต่สำหรับ ARM cortex-M0 เราจะใช้ Atmel Studio เราจะใช้ภาษา C ในทั้งสองแพลตฟอร์ม สิ่งที่ฉันกังวลคือเราจะใช้ไมโครคอนโทลเลอร์ 32 บิตสองตัว (จาก บริษัท เดียวกัน) แต่มีสถาปัตยกรรมที่แตกต่างกัน สิ่งนี้จะทำให้เราต้องเรียนรู้อุปกรณ์ที่แตกต่างกันสองตัวและจะเพิ่ม "ระยะเวลาการเรียนรู้" + เวลาส่งมอบของเรา แต่ในทางกลับกันฉันก็คิดเช่นกันเนื่องจากเราจะใช้ C-Language ในทั้งสองกรณีเส้นโค้งการเรียนรู้สำหรับ ARM นั้นไม่ควรที่จะได้ยินและมันก็คุ้มค่าที่จะสำรวจตัวประมวลผลนั้นด้วย

คำถามหลักของฉันคือความแตกต่างของสถาปัตยกรรมที่เกิดขึ้นเมื่อเราเขียนโปรแกรมในภาษา C เนื่องจากมันให้สิ่งที่เป็นนามธรรมของ internals ของไมโครคอนโทรลเลอร์ และอะไรคือความแตกต่างที่สำคัญใน MPLAP และ Atmel Studioเมื่อพิจารณาการวางโปรแกรมภาษา C


2
หากสิ่งต่าง ๆ ทำงานร่วมกับ PIC32 แล้วจุดเปลี่ยนคืออะไร? แม้ว่ารหัสจะสมบูรณ์พอร์ต (จะไม่เกิดขึ้น) แต่ก็ยังมีห่วงโซ่เครื่องมือใหม่และ IDE ที่จะคุ้นเคย ประเด็นคืออะไร? การเปลี่ยนเพื่อเหตุผลทางศาสนาหรือเป็น "ARM based" (หรือสิ่งอื่นใด) เป็นเรื่องโง่ คุณต้องมีเหตุผลที่ดี แต่คุณไม่ได้แสดงให้เราเห็น
Olin Lathrop

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

สิ่งหนึ่งที่ฉันค้นพบว่า Atmel Studio มอบช่วงเวลาที่เหนือกว่าวิดีโอ YouTube
วิศวกร

คำตอบ:


20

นี่เป็นหัวข้อที่ค่อนข้างมีความเห็น ฉันสามารถพูดได้ด้วยตัวเอง (AVR, ARM, MSP430)

ความแตกต่าง 1 (สำคัญที่สุด) อยู่ในอุปกรณ์ต่อพ่วง MCU แต่ละตัวมี UART, SPI, ตัวจับเวลาและอื่น ๆ ที่คล้ายกัน - เพียงแค่ลงทะเบียนชื่อและบิตต่างกัน ส่วนใหญ่มันเป็นปัญหาหลักที่ฉันต้องจัดการเมื่อย้ายรหัสระหว่างชิป โซลูชัน: เขียนไดรเวอร์ของคุณด้วย API ทั่วไปเพื่อให้แอปพลิเคชันของคุณสามารถพกพาได้

ข้อแตกต่างที่ 2 คือสถาปัตยกรรมหน่วยความจำ หากคุณต้องการให้ค่าคงที่ในแฟลชบน AVR คุณต้องใช้คุณสมบัติพิเศษและฟังก์ชั่นพิเศษเพื่ออ่าน ในโลก ARM คุณเพิ่งอ่านซ้ำตัวชี้เนื่องจากมีพื้นที่ที่อยู่เดียว (ฉันไม่รู้ว่า PIC ขนาดเล็กจัดการกับมันได้อย่างไร แต่จะสมมติว่าใกล้กับ AVR)

ความแตกต่าง 3 คือการประกาศและการจัดการอินเตอร์รัปต์ avr-gccมีISR()มาโคร ARM มีเพียงชื่อฟังก์ชั่น (เช่น someUART_Handler () - หากคุณใช้ส่วนหัว CMSIS และรหัสเริ่มต้น) ARM สามารถติดตั้งเวกเตอร์ขัดจังหวะได้ทุกที่ (รวมถึง RAM) และแก้ไขที่รันไทม์ (สะดวกมากถ้าคุณมีตัวอย่างโปรโตคอล UART ที่ต่างกันสองตัวที่สามารถสลับได้) AVR มีเพียงตัวเลือกในการใช้พาหะใน "แฟลชหลัก" หรือ "ส่วน bootloader" (ดังนั้นหากคุณต้องการจัดการอินเตอร์รัปต์ต่างกันคุณต้องใช้ifคำสั่ง)

ข้อแตกต่าง 4 - โหมดสลีปและการควบคุมพลังงาน หากคุณมีความต้องการใช้พลังงานต่ำสุดคุณจะต้องใช้คุณสมบัติทั้งหมดของ MCU สิ่งนี้อาจแตกต่างกันมากระหว่าง MCU - บางตัวมีโหมดประหยัดพลังงานที่หยาบกว่าบางตัวสามารถเปิด / ปิดการใช้งานอุปกรณ์ต่อพ่วงแต่ละตัวได้ MCUs บางตัวมีตัวควบคุมที่ปรับได้เพื่อให้คุณสามารถเรียกใช้พวกเขาด้วยแรงดันไฟฟ้าต่ำที่ความเร็วช้าลง ฯลฯ ฉันไม่เห็นวิธีที่ง่ายในการบรรลุประสิทธิภาพเดียวกันบน MCU (สมมติว่า) ด้วยโหมดพลังงานทั่วโลก 3 โหมดและโหมดพลังงาน 7 โหมด การควบคุมนาฬิกาอุปกรณ์ต่อพ่วงแต่ละอัน

สิ่งที่สำคัญที่สุดเพียงอย่างเดียวเมื่อคำนึงถึงความสะดวกในการพกพาคือการแยกรหัสของคุณออกเป็นส่วน ๆ ที่ขึ้นกับฮาร์ดแวร์ (ไดรเวอร์) และส่วนที่ไม่ขึ้นกับฮาร์ดแวร์ คุณสามารถพัฒนาและทดสอบหลังบนพีซีปกติด้วยไดรเวอร์จำลอง (เช่นคอนโซลแทน UART) สิ่งนี้ช่วยฉันได้หลายครั้งเนื่องจาก 90% ของรหัสแอปพลิเคชันเสร็จสมบูรณ์ก่อนที่ฮาร์ดแวร์ต้นแบบจะออกมาจากเตาอบ reflow :)

ในความคิดของฉันสิ่งที่ดีเกี่ยวกับ ARM คือ "monoculture" - ความพร้อมของคอมไพเลอร์มากมาย (gcc, Keil, IAR ... เพื่อชื่อไม่กี่), IDEsที่ฟรีและสนับสนุนจำนวนมาก(อย่างน้อยสำหรับ NXP, STM32, Silicon Labs, Nordic) เครื่องมือดีบักมากมาย (SEGGER - โดยเฉพาะอย่างยิ่ง Ozone, ULINK, OpenOCD ... ) และผู้จำหน่ายชิปจำนวนมาก (ฉันจะไม่เริ่มตั้งชื่อพวกเขาด้วยซ้ำ) PIC32 ส่วนใหญ่ถูก จำกัด ไว้ที่ Microchip (แต่จะสำคัญเฉพาะถ้าคุณไม่ชอบเครื่องมือของพวกเขา

เมื่อมันมาถึงรหัส C มันเหมือนกัน 99% ifข้อความสั่งเหมือนกันการวนซ้ำในลักษณะเดียวกัน อย่างไรก็ตามคุณควรใส่ใจเกี่ยวกับขนาดของคำ ตัวอย่างเช่นการforวนซ้ำบน AVR นั้นเร็วที่สุดหากคุณใช้uint8_tสำหรับตัวนับในขณะที่ ARM uint32_tเป็นชนิดที่เร็วที่สุด (หรือint32_t) ARM จะต้องตรวจสอบโอเวอร์โฟลว์ 8 บิตทุกครั้งหากคุณใช้งานขนาดเล็กกว่านี้

การเลือก MCU และ / หรือผู้ขายโดยทั่วไปส่วนใหญ่เกี่ยวกับการเมืองและโลจิสติกส์ (ยกเว้นกรณีที่คุณมีข้อ จำกัด ทางวิศวกรรมที่ชัดเจนมากเช่น: อุณหภูมิสูง - ใช้ MSP430 หรือ Vorago) แม้ว่าแอปพลิเคชันสามารถทำงานกับอะไรก็ได้และมีเพียง 5% ของรหัส (ไดรเวอร์) ที่ต้องได้รับการพัฒนาและสนับสนุนตลอดอายุการใช้งานของผลิตภัณฑ์ - มันยังคงเป็นค่าใช้จ่ายเพิ่มเติมสำหรับ บริษัท สถานที่ทั้งหมดที่ฉันเคยทำงานมีผู้ขายและสาย MCU ที่ชื่นชอบ (เช่น "เลือก Kinetis ใดก็ได้ที่คุณต้องการเว้นแต่จะมีเหตุผลที่ดีมากในการเลือกสิ่งที่แตกต่าง") นอกจากนี้ยังช่วยถ้าคุณมีคนอื่นขอความช่วยเหลือดังนั้นในฐานะผู้จัดการฉันจะหลีกเลี่ยงการมีแผนกพัฒนา 5 คนที่ทุกคนใช้ชิปแตกต่างกันโดยสิ้นเชิง


3
“ AVR นั้นเร็วที่สุดหากคุณใช้ uint8_t สำหรับตัวนับในขณะที่ ARM uint32_t เป็นประเภทที่เร็วที่สุด (หรือ int32_t) ARM จะต้องตรวจสอบโอเวอร์โฟลว์ 8 บิตทุกครั้งหากคุณใช้งานขนาดเล็กกว่านี้” คุณสามารถใช้ uint_fast8_t หากคุณต้องการอย่างน้อย 8 บิต
Michael

@Michael - ให้แน่ใจว่าคุณสามารถใช้ _fast ประเภท แต่คุณไม่สามารถนับบนพฤติกรรมล้นได้ ใน stdint.h gcc ของฉันฉันมี "typedef int uint_fast8_t" ที่ไม่ได้ลงนาม "ซึ่งโดยทั่วไปคือ uint32_t :)
filo

การพยายามเขียน API ที่มีประสิทธิภาพเป็นสากลและสมบูรณ์นั้นเป็นเรื่องยากเนื่องจากแพลตฟอร์มต่างๆมีความสามารถแตกต่างกัน CPU อาจมีความสำคัญน้อยกว่าอุปกรณ์ต่อพ่วงและการตัดสินใจในการออกแบบ ตัวอย่างเช่นอุปกรณ์บางตัวอนุญาตให้กำหนดค่าอุปกรณ์ต่อพ่วงต่าง ๆ ได้ตลอดเวลาในเวลาไม่เกินสองสามไมโครวินาทีในขณะที่อุปกรณ์อื่นอาจต้องการหลายขั้นตอนกระจายออกไปหลายร้อยไมโครวินาทีหรือแม้กระทั่งมิลลิวินาที ฟังก์ชั่น API ที่มีไว้สำหรับรูปแบบในอดีตอาจใช้งานได้ภายในรูทีนการบริการขัดจังหวะที่ทำงานที่ 10,000Hz แต่ ...
supercat

... ไม่สามารถรองรับการใช้งานบนแพลตฟอร์มที่ต้องการกระจายการดำเนินงานไปหลายร้อยไมโครวินาที ฉันไม่รู้ว่าทำไมนักออกแบบฮาร์ดแวร์จึงไม่พยายามอย่างหนักที่จะสนับสนุน "การดำเนินการอย่างรวดเร็วได้ตลอดเวลา" ความหมายของ API แต่หลายคนใช้แบบจำลองที่ประสานการทำงานของแต่ละบุคคลแทนที่จะเป็นสถานะดังนั้นถ้ามีการร้องขอเช่น เปิดอุปกรณ์และรหัสตระหนักว่าไม่จำเป็นต้องเปิดใช้งานรหัสต้องรอให้อุปกรณ์เปิดใช้งานก่อนที่จะสามารถออกคำขอให้ปิดได้ การจัดการที่ราบรื่นใน API เพิ่มภาวะแทรกซ้อนที่สำคัญ
supercat

11

ฉันใช้ MCU หลายตัวจากผู้ผลิตสี่ราย งานหลักทุกครั้งอีกครั้งคือการทำความคุ้นเคยกับอุปกรณ์ต่อพ่วง

ตัวอย่างเช่นตัว UART นั้นไม่ซับซ้อนเกินไปและฉันพบพอร์ตไดรเวอร์ของฉันได้อย่างง่ายดาย แต่ครั้งสุดท้ายที่ฉันใช้เวลาเกือบหนึ่งวันในการรับนาฬิกาหมุด I / O ขัดจังหวะเปิดใช้งาน ฯลฯ แยกออก

GPIO นั้นซับซ้อนมาก ชุดบิต, บิตชัดเจน, บิตสลับ, ฟังก์ชั่นพิเศษเปิด / ปิดการใช้งาน, ไตรสถานะ ถัดไปคุณจะได้รับการขัดจังหวะ: ใด ๆ เพิ่มขึ้นลดลงระดับต่ำระดับสูงล้างตัวเองหรือไม่

จากนั้นก็มี I2C, SPI, PWM, Timers และอุปกรณ์ต่อพ่วงอีกสองประเภทที่มีนาฬิกาของตัวเองและทุกครั้งที่รีจิสเตอร์แตกต่างกับบิตใหม่ สำหรับข้อมูลทั้งหมดนั้นใช้เวลาหลายชั่วโมงในการอ่านแผ่นข้อมูลวิธีตั้งค่าบิตภายใต้สถานการณ์ใด

ผู้ผลิตรายสุดท้ายมีตัวอย่างรหัสจำนวนมากซึ่งฉันพบว่าใช้ไม่ได้ ทุกอย่างเป็นนามธรรม แต่เมื่อฉันตามมันลงไปรหัสก็ผ่านไปหกครั้ง! ระดับการเรียกใช้ฟังก์ชันเพื่อตั้งค่าบิต GPIO ดีถ้าคุณมีโปรเซสเซอร์ 3GHz แต่ไม่ได้อยู่ใน MCU 48MHz รหัสของฉันในที่สุดคือบรรทัดเดียว:

GPIO->set_output = bit.

ฉันได้ลองใช้ไดรเวอร์ทั่วไปมากกว่า แต่ฉันได้เลิกใช้แล้ว ใน MCU คุณมักจะดิ้นรนกับพื้นที่และวงจรนาฬิกา ฉันพบว่าชั้นนามธรรมเป็นคนแรกที่ออกไปนอกหน้าต่างถ้าคุณสร้างรูปแบบคลื่นเฉพาะในรูทีนการขัดจังหวะที่เรียกว่าที่ 10KHz

ดังนั้นตอนนี้ฉันมีทุกอย่างทำงานและฉันวางแผนที่จะไม่สลับอีกครั้งเว้นแต่จะมีเหตุผลที่ดีมาก

ทั้งหมดข้างต้นจะต้องมีการตัดจำหน่ายมากกว่าจำนวนสินค้าที่คุณขายและสิ่งที่คุณบันทึก ขายล้านบาท: ประหยัด 0.10 เพื่อเปลี่ยนไปใช้ประเภทอื่นหมายความว่าคุณสามารถใช้จ่าย 100.000 ชั่วโมงกับซอฟต์แวร์ ขาย 1,000 คุณมีเพียง 100 ใช้จ่าย


1
โดยส่วนตัวนี่คือเหตุผลที่ฉันติดกับแอสเซมเบลอร์ ไบนารีที่น่ารักไม่มีสิ่งที่เป็นนามธรรม
Ian Bland

ตัวประมวลผลล่วงหน้าของ C สามารถทำได้ดีกับสิ่งต่าง ๆ โดยเฉพาะอย่างยิ่งเมื่อรวมกับ __builtin_constant intrinsics หากหนึ่งกำหนดค่าคงที่สำหรับบิต I / O แต่ละรูปแบบ (หมายเลขพอร์ต * 32 + หมายเลขบิต) เป็นไปได้ที่จะเขียนแมโครOUTPUT_HI(n)ซึ่งจะให้โค้ดเทียบเท่ากับGPIOD->bssr |= 0x400;ถ้าnเป็นค่าคงที่เช่น 0x6A แต่เรียกรูทีนย่อยง่ายถ้าnเป็น ไม่คงที่ ดังที่ได้กล่าวไปแล้ว API ของผู้ให้บริการส่วนใหญ่ที่ฉันได้เห็นอยู่ในช่วงระหว่างปานกลางและน่ากลัว
supercat

8

นี่เป็นความเห็น / ความคิดเห็นมากกว่าคำตอบ

คุณไม่ต้องการและไม่ควรเขียนโปรแกรมใน C. C ++ เมื่อใช้อย่างถูกวิธีจะดีกว่ามาก (ตกลงฉันต้องยอมรับเมื่อใช้ในทางที่ผิดมันแย่กว่า C. ) ซึ่ง จำกัด คุณให้ชิปที่มีคอมไพเลอร์ C ++ ที่ทันสมัยซึ่งเป็นสิ่งที่สนับสนุน GCC รวมถึง AVR (ด้วย ข้อ จำกัด บางอย่าง filo กล่าวถึงปัญหาของพื้นที่ที่อยู่ที่ไม่สม่ำเสมอ) แต่ยกเว้น PICs เกือบทั้งหมด (PIC32 สามารถรองรับได้ แต่ฉันยังไม่เห็นพอร์ตที่เหมาะสม)

เมื่อคุณเขียนโปรแกรมอัลกอริธึมใน C / C ++ ความแตกต่างระหว่างตัวเลือกที่คุณพูดถึงนั้นมีขนาดเล็ก (ยกเว้นว่าชิป 8 หรือ 16 บิตจะเสียเปรียบอย่างมากเมื่อคุณทำเลขคณิต 16, 32 หรือสูงกว่า) เมื่อคุณต้องการออนซ์ประสิทธิภาพครั้งสุดท้ายคุณอาจจำเป็นต้องใช้แอสเซมเบลอร์ (ทั้งของคุณเองหรือรหัสที่จัดทำโดยผู้จัดจำหน่ายหรือบุคคลที่สาม) ในกรณีนี้คุณอาจต้องการพิจารณาชิปที่คุณเลือกอีกครั้ง

เมื่อคุณเขียนโค้ดลงในฮาร์ดแวร์คุณสามารถใช้เลเยอร์นามธรรมบางอย่าง (มักจัดทำโดยผู้ผลิต) หรือเขียนของคุณเอง (ตามแผ่นข้อมูลและ / หรือรหัสตัวอย่าง) abstractions ที่มีอยู่ของ IME (mbed, cmsis, ... ) มักจะใช้งานได้ (เกือบ) ถูกต้อง แต่ล้มเหลวอย่างมากในการทำงาน พวกเขาต้องการแสดงการทำงานทั้งหมดของชิปเฉพาะกับคุณซึ่งในเกือบทุกกรณีที่คุณไม่ต้องการและไม่สนใจและจะล็อครหัสของคุณกับผู้จำหน่ายรายนั้น (และอาจเป็นชิปนั้น)

นี้จะเป็น C ++ สามารถทำได้ดีกว่ามากเมื่อทำอย่างถูกต้องชุดขาสามารถไปถึง 6 ชั้นหรือมากกว่านามธรรมเลย (เพราะที่ทำให้ดีขึ้น (แบบพกพา) อินเตอร์เฟซและรหัสสั้นเป็นไปได้!) ให้อินเตอร์เฟซที่เป็นเป้าหมายอิสระ สำหรับกรณีง่าย ๆและยังคงส่งผลให้รหัสเครื่องเดียวกับที่คุณจะเขียนในแอสเซมเบลอร์

ตัวอย่างของรูปแบบการเขียนที่ฉันใช้ซึ่งอาจทำให้คุณกระตือรือร้นหรือหันเหความกลัว:

// GPIO part of a HAL for atsam3xa
enum class _port { a = 0x400E0E00U, . . . };

template< _port P, uint32_t pin >
struct _pin_in_out_base : _pin_in_out_root {

   static void direction_set_direct( pin_direction d ){
      ( ( d == pin_direction::input )
         ? ((Pio*)P)->PIO_ODR : ((Pio*)P)->PIO_OER )  = ( 0x1U << pin );
   }

   static void set_direct( bool v ){
      ( v ? ((Pio*)P)->PIO_SODR : ((Pio*)P)->PIO_CODR )  = ( 0x1U << pin );    
   }
};

// a general GPIO needs some boilerplate functionality
template< _port P, uint32_t pin >
using _pin_in_out = _box_creator< _pin_in_out_base< P, pin > >;

// an Arduino Due has an on-board led, and (suppose) it is active low
using _led = _pin_in_out< _port::b, 27 >;
using led  = invert< pin_out< _led > >;

ในความเป็นจริงมีบางสิ่งที่เป็นนามธรรมมากขึ้น แต่การใช้งานครั้งสุดท้ายของผู้นำก็เปิดใช้งานไม่แสดงความซับซ้อนหรือรายละเอียดของเป้าหมาย (สำหรับ arduin uno หรือยาเม็ดสีน้ำเงิน ST32 รหัสจะเหมือนกัน)

target::led::init();
target::led::set( 1 );

คอมไพเลอร์ไม่ได้ถูกข่มขู่โดยเลเยอร์เหล่านั้นทั้งหมดและเนื่องจากไม่มีฟังก์ชั่นเสมือนที่เกี่ยวข้องกับเครื่องมือเพิ่มประสิทธิภาพที่มองเห็นทุกสิ่ง

 mov.w  r2, #134217728  ; 0x8000000
 ldr    r3, [pc, #24]   
 str    r2, [r3, #16]
 str    r2, [r3, #48]   

ซึ่งเป็นวิธีที่ฉันจะได้เขียนไว้ในแอสเซมเบลอร์ - ถ้าฉันรู้ว่าการลงทะเบียน PIO สามารถใช้กับออฟเซ็ตจากฐานทั่วไป ในกรณีนี้ฉันอาจจะ แต่คอมไพเลอร์ดีกว่าที่จะเพิ่มประสิทธิภาพสิ่งต่าง ๆ มากกว่าฉัน

ดังนั้นเท่าที่ฉันมีคำตอบก็คือ: เขียนเลเยอร์สิ่งที่เป็นนามธรรมสำหรับฮาร์ดแวร์ของคุณ แต่ทำใน C ++ (แนวความคิดเทมเพลต) ที่ทันสมัยดังนั้นมันจึงไม่เป็นอันตรายต่อประสิทธิภาพการทำงานของคุณ คุณสามารถสลับไปยังชิปอื่นได้อย่างง่ายดาย คุณยังสามารถเริ่มพัฒนาชิปสุ่มที่คุณวางไว้มี familiair มีเครื่องมือดีบั๊กสำหรับและอื่น ๆ และเลื่อนตัวเลือกสุดท้ายจนกระทั่งในภายหลัง (เมื่อคุณมีข้อมูลเพิ่มเติมเกี่ยวกับหน่วยความจำที่ต้องการความเร็วซีพียู ฯลฯ )

IMO หนึ่งในข้อบกพร่องของการพัฒนาที่ฝังอยู่คือการเลือกชิปก่อน (มันเป็นคำถามที่ถามบ่อยในฟอรัมนี้: ฉันควรเลือกชิปตัวใดสำหรับ .... คำตอบที่ดีที่สุดคือโดยทั่วไป: มันไม่สำคัญ)

(แก้ไข - ตอบสนองต่อ "ดังนั้นประสิทธิภาพฉลาด, C หรือ C ++ จะอยู่ในระดับเดียวกันหรือไม่")

สำหรับโครงสร้างเดียวกัน C และ C ++ เหมือนกัน C ++ มีโครงสร้างมากขึ้นสำหรับนามธรรม (เพียงไม่กี่: คลาส, แม่แบบ, constexpr) ซึ่งสามารถเช่นเดียวกับเครื่องมือใด ๆ ที่จะใช้สำหรับการที่ดีหรือไม่ดี เพื่อให้การอภิปรายน่าสนใจยิ่งขึ้น: ทุกคนไม่เห็นด้วยกับสิ่งที่ดีหรือไม่ดี ...


ดังนั้นประสิทธิภาพที่ฉลาด C หรือ C ++ จะอยู่ในระดับเดียวกันหรือไม่ ฉันคิดว่า C ++ จะมีงานโอเวอร์โหลดมากขึ้น แน่นอนคุณชี้ให้ฉันในทิศทางที่ถูกต้อง, C + + เป็นวิธีที่จะไปไม่ได้ C.
วิศวกร

เทมเพลต C ++ บังคับให้เกิด polymorphism แบบคอมไพล์เวลาซึ่งอาจเป็นศูนย์ (หรือค่าลบ) ในแง่ของประสิทธิภาพเนื่องจากโค้ดจะถูกรวบรวมสำหรับแต่ละกรณีการใช้งานที่เฉพาะเจาะจง สิ่งนี้มีแนวโน้มที่จะให้ยืมตัวเองได้ดีที่สุดในการกำหนดเป้าหมายความเร็ว (O3 สำหรับ GCC) ความแตกต่างในเวลาทำงานเช่นฟังก์ชั่นเสมือนจริงอาจได้รับโทษมากกว่าแม้ว่าจะง่ายต่อการบำรุงรักษาและในบางกรณีก็ดีพอ
ฮันส์

1
คุณอ้างว่า C ++ นั้นดีกว่า แต่หลังจากนั้นคุณก็ไปใช้ C-style casts สำหรับความอัปยศ.
JAB

@ JAB ฉันไม่เคยรู้สึกมากกับการแสดงในรูปแบบใหม่ แต่ฉันจะลองดู แต่ลำดับความสำคัญปัจจุบันของฉันอยู่ในส่วนอื่น ๆ ของห้องสมุดนี้ ปัญหาที่แท้จริงคือแน่นอนว่าฉันไม่สามารถผ่านตัวชี้เป็นพารามิเตอร์เทมเพลตได้
Wouter van Ooijen

@ แฮนสไตล์ cto ของฉัน (รวบรวมเวลาวัตถุ) มีกรณีการใช้งานที่ค่อนข้างแคบ (ใกล้กับฮาร์ดแวร์สถานการณ์ที่รู้จักกันเวลารวบรวม) มันเป็น C-killer มากกว่าการแทนที่การใช้ OO เสมือนจริงแบบ tranditional Bycatch ที่มีประโยชน์คือการไม่มีทางอ้อมทำให้สามารถคำนวณขนาดสแต็กได้
Wouter van Ooijen

4

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

C ค่อนข้างยืดหยุ่นอยู่แล้วในตัวมันคือ แพลตฟอร์มทั้งหมดที่คุณเลือกมี GCC / คอมไพเลอร์โฆษณาที่มีมาตรฐานภาษา C89 และ C99 ซึ่งหมายความว่าคุณสามารถเรียกใช้โค้ดที่คล้ายกันในทุกแพลตฟอร์ม

มีข้อควรพิจารณาบางประการ:

  • สถาปัตยกรรมบางอย่างคือ Von Neumann (ARM, MIPS) และอื่น ๆ คือ Harvard ข้อ จำกัด หลักเกิดขึ้นเมื่อโปรแกรม C ของคุณจำเป็นต้องอ่านข้อมูลจาก ROM เช่นการพิมพ์สตริงมีข้อมูลที่กำหนดเป็น "const" หรือคล้ายกัน

แพลตฟอร์ม / คอมไพเลอร์บางตัวสามารถซ่อน "ข้อ จำกัด " นี้ได้ดีกว่าสิ่งอื่น เช่นใน AVR คุณต้องใช้มาโครเฉพาะเพื่ออ่านข้อมูล ROM ใน PIC24 / dsPIC นอกจากนี้ยังมีการประมูล tblrd โดยเฉพาะ อย่างไรก็ตามในบางส่วนยังมีคุณสมบัติ"การมองเห็นพื้นที่โปรแกรม" (PSVPAG) ที่มีอยู่ซึ่งอนุญาตให้ทำการแมปหน้าของ FLASH เป็น RAM ทำให้สามารถระบุข้อมูลได้ทันทีโดยไม่ต้องใช้ tblrd คอมไพเลอร์สามารถทำสิ่งนี้ได้อย่างมีประสิทธิภาพ

ARM และ MIPS คือ Von Neumann ดังนั้นจึงมีพื้นที่หน่วยความจำสำหรับ ROM, RAM และอุปกรณ์ต่อพ่วงที่บรรจุลงใน 1 บัส คุณจะไม่สังเกตเห็นความแตกต่างระหว่างการอ่านข้อมูลจาก RAM หรือ "ROM"

  • หากคุณดำน้ำด้านล่าง C และดูคำแนะนำที่สร้างขึ้นสำหรับการดำเนินการบางอย่างคุณจะพบความแตกต่างขนาดใหญ่รอบ I / O ARM และ MIPS เป็น RISC โหลดเก็บสถาปัตยกรรมทะเบียน ซึ่งหมายความว่าการเข้าถึงข้อมูลบนบัสหน่วยความจำต้องทำตามคำแนะนำ MOV นอกจากนี้ยังหมายความว่าการแก้ไขใด ๆ ของค่าอุปกรณ์ต่อพ่วงจะนำไปสู่การดำเนินการอ่าน - แก้ไข - เขียน (RMW) มีชิ้นส่วน ARM บางส่วนที่รองรับ Bit-Banding ซึ่งแม็พ set / clr-bit จะรีจิสเตอร์ในพื้นที่รอบนอก I / O อย่างไรก็ตามคุณต้องใช้รหัสนี้เข้าถึงตัวคุณเอง

ในทางกลับกัน PIC24 อนุญาตให้การดำเนินการ ALU อ่านและเขียนข้อมูลโดยตรงผ่านการกำหนดตำแหน่งทางอ้อม (แม้จะมีการแก้ไขตัวชี้ .. ) นี่มีลักษณะบางอย่างจาก CISC เช่นสถาปัตยกรรมดังนั้นคำสั่ง 1 คำสั่งสามารถทำงานได้มากขึ้น การออกแบบนี้อาจนำไปสู่คอร์ CPU ที่ซับซ้อนมากขึ้น, นาฬิกาที่ต่ำกว่า, การใช้พลังงานที่สูงขึ้น ฯลฯ โชคดีสำหรับคุณที่ได้รับการออกแบบชิ้นส่วนแล้ว ;-)

ความแตกต่างเหล่านี้อาจหมายถึงว่า PIC24 สามารถดำเนินการ wrt I / O "punchy" ได้ดีกว่าชิป ARM หรือ MIPS แบบโอเวอร์คล็อกที่คล้ายกัน อย่างไรก็ตามคุณอาจได้รับชิ้นส่วน ARM / MIPS clocker ที่สูงขึ้นสำหรับข้อ จำกัด ด้านราคา / แพ็คเกจ / การออกแบบเดียวกัน ฉันเดาว่าด้วยคำศัพท์เชิงปฏิบัติฉันคิดว่า "การเรียนรู้แพลตฟอร์ม" จำนวนมากกำลังจับสิ่งที่สถาปัตยกรรมสามารถทำได้และไม่สามารถทำได้การปฏิบัติการสักสองสามชุดที่รวดเร็ว ฯลฯ

  • อุปกรณ์ต่อพ่วงการจัดการนาฬิกา ฯลฯ มีความแตกต่างกันในแต่ละส่วนของครอบครัว การพูดอย่างเคร่งครัดนี่จะเปลี่ยนภายในระบบนิเวศ ARM ระหว่างผู้ขายยกเว้นอุปกรณ์ต่อพ่วง Cortex m ที่ถูกผูกไว้เช่น NVIC และ SysTick

ความแตกต่างเหล่านี้สามารถห่อหุ้มโดยไดรเวอร์อุปกรณ์ แต่ในที่สุดเฟิร์มแวร์ฝังตัวมีการเชื่อมต่อกับฮาร์ดแวร์ในระดับสูงดังนั้นบางครั้งงานที่กำหนดเองจึงไม่สามารถหลีกเลี่ยงได้

นอกจากนี้หากคุณกำลังออกจากระบบนิเวศน์ของ Microchip / Atmel ในอดีตคุณอาจพบว่าชิ้นส่วน ARM ต้องการการตั้งค่าที่มากขึ้นเพื่อให้มันทำงานต่อไป ฉันหมายถึงในแง่ของ; การเปิดใช้งานนาฬิกากับอุปกรณ์ต่อพ่วงจากนั้นกำหนดค่าอุปกรณ์ต่อพ่วงและ "เปิดใช้งาน" ตั้งค่า NVIC แยกจากกันเป็นต้นนี่เป็นเพียงส่วนหนึ่งของกราฟการเรียนรู้ เมื่อคุณอย่าลืมทำสิ่งเหล่านี้ตามลำดับการเขียนไดรเวอร์อุปกรณ์สำหรับไมโครคอนโทรลเลอร์เหล่านี้ทั้งหมดจะรู้สึกคล้ายกันในบางจุด

  • ลองใช้ไลบรารี่เช่น stdint.h, stdbool.h เป็นต้นหากยังไม่ได้ใช้ ประเภทจำนวนเต็มเหล่านี้ทำให้ความกว้างชัดเจนซึ่งทำให้พฤติกรรมของโค้ดสามารถคาดเดาได้มากที่สุดระหว่างแพลตฟอร์ม นี่อาจหมายถึงการใช้จำนวนเต็ม 32- บิตบน 8-bit AVR; แต่ถ้ารหัสของคุณต้องการมัน

3

ใช่และไม่. จากมุมมองของโปรแกรมเมอร์คุณจะซ่อนรายละเอียดของชุดคำสั่งไว้อย่างดีเยี่ยม แต่นั่นก็มีบ้างแล้วที่ไม่เกี่ยวข้องกับอุปกรณ์ต่อพ่วงซึ่งเป็นจุดรวมของการเขียนโปรแกรมไม่ใช่ส่วนหนึ่งของชุดคำสั่ง ในขณะเดียวกันคุณไม่สามารถเปรียบเทียบชิ้นส่วนแฟลช 4096 ไบต์ในชุดคำสั่งเหล่านั้นโดยเฉพาะอย่างยิ่งถ้าใช้ C ปริมาณการใช้แฟลช / หน่วยความจำจะถูกกำหนดอย่างมากโดยชุดคำสั่งและคอมไพเลอร์บางคนไม่ควรเห็นคอมไพเลอร์ อาการไอ) เกิดจากการรวบรวมทรัพยากรของเสียที่เกิดจากการบริโภค การใช้แฟลชอื่น ๆ นั้นเป็นค่าใช้จ่ายที่น้อยกว่า ประสิทธิภาพเป็นปัญหาเมื่อใช้ภาษาระดับสูงและประสิทธิภาพการทำงานในแอปพลิเคชัน MCU ดังนั้นจึงสามารถสร้างความแตกต่างระหว่างการใช้จ่าย $ 3 ต่อบอร์ดสำหรับ mcu หรือ $ 1

ถ้ามันเกี่ยวกับการทำให้การเขียนโปรแกรมง่ายขึ้น (ในราคาโดยรวมของผลิตภัณฑ์) คุณควรจะสามารถดาวน์โหลดแพ็คเกจนักพัฒนาสำหรับ mcu เพื่อให้สถาปัตยกรรมชุดคำสั่งเป็นสิ่งที่คุณไม่เคยเห็นดังนั้นถ้ามันเป็นเรื่องหลักของคุณ ไม่ได้เป็นกังวล มันก็ยังคงมีค่าใช้จ่ายเงินของคุณเท่าที่เป็นค่าใช้จ่ายของสินค้าที่จะใช้ห้องสมุดเหล่านี้ แต่เวลาในการตลาดอาจสั้นลงฉันพบว่าห้องสมุดต้องใช้เวลา / งานมากขึ้นในการใช้ vs การพูดคุยโดยตรงกับอุปกรณ์ต่อพ่วง

บรรทัดล่างสุดชุดคำสั่งเป็นสิ่งที่คุณกังวลน้อยที่สุดไปยังประเด็นที่แท้จริง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.