คุณโครงสร้างโครงการฝังตัวขนาดใหญ่ได้อย่างไร [ปิด]


21

พื้นหลัง :

วิศวกรอิเล็กทรอนิกส์ R&D อาวุโส ( EE เพียงคนเดียวใน บริษัท ) - ฮาร์ดแวร์และการเข้ารหัสไม่ใช่ปัญหา ปัญหาที่ใหญ่ที่สุดของฉันคือการได้รับภาพรวมที่เหมาะสมของโครงการและที่จะเริ่ม

จนถึงตอนนี้ฉันได้ทำโครงการซอฟต์แวร์เพียงเล็กน้อย (โค้ดย่อย 500 บรรทัด) แต่ฉันไม่สามารถนึกภาพตัวเองทำโครงการขนาดใหญ่ได้โดยไม่สูญเสียภาพรวมการทำงานหรือขาดการทำงาน

คุณจะจัดโครงสร้างที่ดีที่สุดได้อย่างไร / คุณใช้เครื่องมือใดในการจัดทำระบบซอฟต์แวร์ฝังตัวขนาดใหญ่

สิ่งที่ฉันกำลังทำอยู่ :

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

คำตอบอะไรที่ฉันกำลังมองหา :

อะไรก็ได้จริง ๆ ฉันจะแยกแยะสิ่งที่ฉันคิดว่าเหมาะสม อาจเป็นหนังสือบทความประสบการณ์ส่วนตัวคำแนะนำ ฯลฯ

ฉันสนใจมากที่รู้ว่าผู้อาวุโสรับมือกับเรื่องนี้อย่างไร


แก้ไข

ก่อนอื่นขอบคุณสำหรับการแบ่งปันประสบการณ์ของคุณ! คำตอบทั้งหมดชื่นชมมาก สิ่งที่ฉันทำจากสิ่งนี้คือ;

  • สร้างเอกสารข้อกำหนดที่ชัดเจนและแม่นยำ
  • สร้างเอกสารการออกแบบซอฟต์แวร์ (ตอนนี้ฉันจะเพิ่มบางอย่าง) แม่แบบเอกสารการออกแบบ
  • คิดในหน่วยที่อาจซ้ำซ้อน (สิ่งที่ฉันต้องมุ่งเน้นเพิ่มเติม)
  • ปฏิบัติตามมาตรฐานการเข้ารหัสสำหรับการจัดโครงสร้างไฟล์ส่วนหัว / ซอร์ส (ไม่เคยทำเช่นนี้) มาตรฐาน Barr กลุ่ม C
  • มุ่งเน้นการสร้างการใช้งานระดับต่ำก่อน (การสื่อสาร ฯลฯ )
  • ใช้รูปแบบการออกแบบที่เป็นไปได้ / เหมาะสม รูปแบบการออกแบบ
  • ตั้งค่าบางอย่างสำหรับการควบคุมการแก้ไข (Github ฯลฯ - ไม่เคยใช้มากขนาดนี้)
  • การรวมการวิจัยอย่างต่อเนื่อง / การปรับใช้อย่างต่อเนื่อง (มีอะไรใหม่ที่ฉันสะดุด) ข้อมูลพื้นฐาน CI & CD

4
คำถามนี้ไม่ได้อยู่ที่นี่ ... อาจเป็นsoftwareengineering.stackexchange.com
Swanand

11
บางทีคำถามนี้อาจเป็นของที่นี่ ฉันยกย่องทีมออกแบบที่มีหลายชิปเมื่อหลายสิบปีที่แล้วและเราติดตามความคืบหน้าโดยแยกย่อยแต่ละส่วนออกเป็นหน้าที่ต่าง ๆ แล้วประมาณสัปดาห์ที่ต้องการสำหรับ (ทีมงานมือใหม่แรงบันดาลใจ แต่มือใหม่) ออกแบบ / ทดสอบ / ตรวจสอบแต่ละฟังก์ชั่น 60+ แม้ว่าเราจะไม่ตรงตามกำหนดการเดิมที่กำหนด แต่ฝ่ายบริหารก็อดทนเพราะพวกเขาสามารถติดตามความคืบหน้าได้อย่างง่ายดายผ่านฟังก์ชั่น 60+ ที่เรารู้ว่าเราจำเป็นต้องออกแบบและรวมเข้าด้วยกัน
analogsystemsrf

13
@Swanand ฉันไม่เห็นด้วย คำถามที่พบบ่อยในหัวข้อกล่าวว่า "[คำถามเกี่ยวกับ ... ] การเขียนเฟิร์มแวร์สำหรับแอพพลิเคชั่นโลหะเปลือยหรือ RTOS" - ฉันจะบอกว่าสิ่งนี้รวมถึงขั้นตอนการวางแผนอย่างแน่นอน คำถามนี้ระบุว่า "ระบบฝังตัวขนาดใหญ่" โดยเฉพาะ
Araho

2
ในขณะที่การเขียนโปรแกรมเฟิร์มแวร์เป็นหัวข้อที่นี่วิธีที่ดีในการดูว่าคำถามกว้างเกินไปหรือไม่และการใช้ความเห็นคือจำนวนคำตอบในช่วงเวลาสั้น ๆ นี่กว้างเกินไปแน่ ๆ ส่วนความช่วยเหลือพูดว่า "ถ้าหนังสือสามารถเขียนได้ .. " และหนังสือได้ถูกเขียนเกี่ยวกับเรื่องนี้!
ท่อ

2
OP ได้สร้างบทสรุปที่ดี ฉันต้องการเน้นย้ำกับพวกเขาว่า GitHub ไม่ใช่วิธีเดียวในการเรียกใช้ที่เก็บ Git คุณสามารถทำได้แบบโลคัลโดยมีหรือไม่มีเซิร์ฟเวอร์ Git พิเศษที่ทำงานอยู่ Git ไม่ได้เป็นรูปแบบเดียวของ Source Control System (SCS) / Version Control System (VCS) แต่เป็นที่นิยมมากในตอนนี้ เมื่อฉันเริ่มต้นในฐานะ EE ที่มีการฝึกอบรม C และ C ++ มากมายฉันไม่มีความรู้สึกต่อสิ่งเหล่านี้
TafT

คำตอบ:


23

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

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

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

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

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

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


3
โดยเฉพาะอย่างยิ่งความต้องการ! ไม่มีอะไรที่เหมือนกับการสร้างผลิตภัณฑ์หรือฟังก์ชั่นที่ทำสิ่งที่ผิด
กังวลฮอบบิท

13

Humpawumpa เขียนคำตอบที่ยอดเยี่ยม ! ฉันต้องการเสริมบางประเด็นของเขา แต่เนื่องจากนี่นานเกินไปที่จะแสดงความคิดเห็นฉันจะเขียนคำตอบแยกต่างหาก

ฉันเคยอยู่ในตำแหน่ง OP ไม่ใช่เป็น EE เพียงคนเดียว แต่เป็น EE เพียงคนเดียวที่ได้ทำการพัฒนา MCU ใน บริษัท ขนาดเล็ก

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

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


1แตกต่างจากผังงานซึ่งเน้นการควบคุมการไหล


12

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

เหตุผลง่าย ๆ :

1ความซับซ้อน โครงการขนาดใหญ่มักจะมีความซับซ้อนที่เกี่ยวข้อง มีการวางแผนโครงการเป็นว่ามีหลายทีมที่เกี่ยวข้องกับวิธีการที่ซับซ้อนได้รับการพิจารณาและจัดทำเอกสาร จำนวนครั้งที่ฉันได้เห็นโครงการขนาดใหญ่ที่ประสบปัญหานั้นสูงและมักจะเป็นเพราะบางสิ่งบางอย่าง 'ลื่นไหลไปตามรอยแตก' อย่าลืมว่าต้องคำนึงถึงการประกอบชิ้นส่วนทางกลด้วยและไม่เพียงแค่สำหรับขนาดของกล่อง - จะต้องมีแผ่นระบายความร้อนหรือไม่? กล่องจะต้องต่อสายดินเพื่อความปลอดภัยหรือไม่ มีคำถามมากมายในหมวดหมู่นี้เพียงอย่างเดียว

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

3 การแบ่งพาร์ติชัน การแบ่งพาร์ติชันมีสองประเภทคือ ฟังก์ชั่นฮาร์ดแวร์และฮาร์ดแวร์ / ซอฟต์แวร์ ประเภทแรกคือการกำหนดบล็อกการทำงานที่แยกต่างหาก (แต่การสื่อสาร) ที่จะต้องมีอยู่ อย่างที่สองคือการแลกเปลี่ยนฮาร์ดแวร์และซอฟต์แวร์ที่ง่ายกว่า (บางครั้ง) แต่โปรดจำไว้ว่าการย้ายสิ่งต่าง ๆ ไปยังซอฟต์แวร์เพิ่มเติมไม่จำเป็นต้องแก้ไขปัญหาฮาร์ดแวร์ การย้ายเข้าสู่ซอฟต์แวร์มากขึ้นจริง ๆ แล้วสามารถเพิ่มความซับซ้อนของฮาร์ดแวร์ในบางสถานการณ์ (แรงม้าประมวลผลมากขึ้น, อินเทอร์เฟซที่ซับซ้อนและอื่น ๆ )

การเชื่อมต่อ4 กระบวนการแบ่งพาร์ติชันจะช่วยกำหนดอินเตอร์เฟสภายใน อินเทอร์เฟซภายนอกมักเป็นส่วนหนึ่งของข้อกำหนดโดยรวม (แม้ว่าจะไม่เสมอไป) มีหลายวิธีสำหรับส่วนต่าง ๆ ของระบบในการทำงานร่วมกันซึ่งอาจเป็นโปรโตคอลการสื่อสารที่ซับซ้อนหรือเพียงแค่การส่งสัญญาณที่ดี / ไม่ดี

5 การตรวจสอบ นี่คือส่วนผสมของการทดสอบระดับต่ำ (สำหรับฮาร์ดแวร์และไดรเวอร์) และระดับระบบ การทำโครงการในบล็อกที่กำหนดไว้อย่างดีช่วยให้มีการตรวจสอบที่มีประสิทธิภาพ (ซึ่งอาจเกิดจากการวิเคราะห์หรือการทดสอบจริงและมักจะเป็นส่วนผสมของทั้งสองการอัปเดตการออกแบบอาจใช้อาร์กิวเมนต์ที่คล้ายคลึงกัน)

6มาตรฐาน ฉันใช้มาตรฐานการเข้ารหัสและการวาดภาพราวกับว่ามันเป็นทีมที่ใหญ่กว่า ฉันใช้มาตรฐานการเข้ารหัสของกลุ่ม Barr เนื่องจากพวกเขาไม่ได้มีภาระมากเกินไป แต่จะช่วยป้องกันบั๊กหลายคลาสที่อยู่ในโค้ด สำหรับเอกสารเอาท์พุท PCB ฉันติดตามIPC-D-326 (ซึ่งเรียก IPC-D-325) เนื่องจากเป็นวิธีที่ได้รับการพิสูจน์แล้วในการสื่อสารความตั้งใจของฉันต่อผู้ประดิษฐ์ PCB และแอสเซมเบลอร์ สิ่งนี้อาจดูแปลก แต่การมีวินัยในการทำตามมาตรฐานหลายอย่างนั้นหมายความว่าคุณภาพนั้นสอดคล้องกัน

7การควบคุมเวอร์ชัน ฉันใช้การควบคุมการแก้ไขสำหรับทุกส่วนของโครงการ (ระบบฮาร์ดแวร์ซอฟต์แวร์กลไกข้อกำหนดการทดสอบ - ทุกอย่าง) เครื่องมือ CAD ที่ฉันใช้รองรับการกำหนดรุ่นเช่นเดียวกับซอฟต์แวร์และเครื่องมือสร้าง FPGA ทั้งหมด

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

การทำสิ่งเหล่านี้ทั้งหมดเพิ่มเวลาล่วงหน้า แต่เป็นเส้นทางที่เร็วขึ้นสำหรับระบบฝังตัวที่ซับซ้อน


5

คำตอบอื่น ๆ ให้คำแนะนำที่ดีมากมาย นี่คือสองสิ่งที่ฉันพบว่าสำคัญที่สุดในอาชีพการพัฒนาที่ฝังตัวของฉัน:

  1. ทำโค้ดให้มากเป็นโมดูลแยกกันกำหนดไว้ให้ดีที่สุด
  2. ทำให้โมดูลทดสอบได้โดยอัตโนมัติบนพีซี

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


4

เพื่อเพิ่มคำตอบที่มีอยู่ ...

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

เมื่อคุณสร้างอินเทอร์เฟซระดับต่ำแน่นอนว่าคุณต้องใช้ชุดทดสอบ หากคุณออกแบบสิ่งนี้เพื่อเชื่อมต่อกับพีซีตั้งแต่เริ่มต้น (อาจมีพอร์ต RS-232, อาจเป็น USB, บางทีอาจเป็น telnet ผ่าน Ethernet) จากนั้นคุณสามารถเก็บอินเทอร์เฟซชุดทดสอบนี้ไว้ในขณะที่คุณสร้างแอปพลิเคชันของคุณ คุณสามารถเพิ่ม hooks harness สำหรับการทดสอบเพิ่มเติมได้ในขณะที่แอปพลิเคชันมีรูปทรงและจะให้คุณทดสอบการถดถอยของโค้ดเมื่อคุณดำเนินการต่อไป


4

ฉันมักจะคิดคำถามสี่ข้อ สองรายการแรกเป็นของการเริ่มต้นของโครงการระบบสองรายการถัดไปจนถึงที่สุด

  1. พวกเขาต้องการระบบหรือไม่ ระบบจะแก้ปัญหาของลูกค้าในเวลาและระดับราคาที่พวกเขาจะยอมรับหรือไม่? ปัญหาที่พบบ่อยคือการสร้างระบบที่ลูกค้าจะไม่ใช้

  2. เราสามารถสร้างระบบนั้นได้จริงหรือ จะเป็นไปได้หรือไม่ที่จะมอบประสิทธิภาพความแม่นยำการใช้พลังงานที่จำเป็น ...


การสร้างต้นแบบต้นเป็นวิธีที่ดีในการตอบคำถามสองข้อแรกนี้ การลดความเสี่ยงมีความสำคัญอย่างยิ่งในระยะแรก


คำถามสองข้อถัดไปมีการกำหนดเป้าหมายมากขึ้นในระยะต่อมาของโครงการ:

  1. พวกเราเสร็จแล้วจริงเหรอ? ทุกอย่างถูกออกแบบเขียนทดสอบทดสอบและส่งมอบ

  2. พวกเขาใช้ระบบจริงเหรอ?

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