Ett embedded-OS

Berätta om dina pågående projekt.
Mr Andersson
Inlägg: 1394
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Ett embedded-OS

Inlägg av Mr Andersson »

Mitt (långtids)projekt är att skapa ett eget operativsystem från grunden, som ska styra ett annat projekt jag också jobbar med. (Tråd om det kommer senare.)
Om någon annan går i samma tankar kanske det här kan bli en liten hjälp hur man gör, eller kanske mer troligt hur man inte bör göra :lol:


Varför göra ett eget OS när det redan finns så många öppna mcu-OS på nätet?
Jag har programmerat C/C++ i ganska många år, men har inte så mycket erfarenhet av mcu-miljöer annat än lite blinkade LEDs på olika arkitekturer så det här är tänkt att bli ett utbildningsmoment.
Målet är att få ett fungerande OS, inte ett högpresterande OS. Dessutom behöver jag inte hård RTOS-funktionalitet.
Jag kommer försöka göra så mycket som möjligt själv och inte förlita mig på färdiga vendor-bibliotek.

Jag har inte någon detaljerad plan för vad projektet ska innehålla utan kommer att ta saker allt eftersom jag kommer på att jag behöver dem.
Ja, jag vet att alla "experter" säger att man sparar mycket tid på att planera noggrannt först men det är så tråkigt.
Jag läste någonstans att det kallas för "big bang"-metoden, man slänger ihop olika delar tills allt exploderar. Sen bygger man något nytt av resterna som överlever. :D

Tänkta funktioner för mitt OS (härefter kallat mos tills jag kommer på något bättre namn)

Multitasking
├ Preemptive multitasking. En process som tar mycket processortid ska inte kunna låsa systemet.
├ Starta processer från filsystemet. Så att användarprocesser inte behöver hårdkodas. Ger en modulär design där man kan uppdatera specifika delar utan att starta om hela systemet.
└ Virtuellt minne (utan swap space). För att isolera processer från varandra. En kraschande process ska inte kunna ta någon annan med sig i fallet.

Filsystem
├ Något standard-filsystem, exakt vilket ej bestämt ännu. För att enkelt kunna överföra filer mellan mos och pc via sd-kort. FAT är enkelt, men lite väl begränsat.
├ Abstrakt fil-API. En process ska inte behöva bekymra sig över om filen ligger på sd, flash, eller någon annanstans utan samma API används till allt och OSet ser till att det blir rätt.
└ Kanske NFS och/eller SMB. (Ska det tillhöra filsystemet eller nätverket?)

Nätverk
├ 802.1Q VLAN.
├ IPv4 är ett måste. Kanske v6 också beroende på senare behov.
├ SSL/TLS, kanske IPSec. Osäker på om SSL ska räknas till nätverkssystemet eller ligga på en högre nivå.
└ Kanske NFS och/eller SMB. (Ska det tillhöra filsystemet eller nätverket?)

Övrigt
└ Saker som jag behöver som jag inte vet om än.. :doubt:

Tidsbudget
Ingen. Det är ett hobbyprojekt utan deadline.
Ja det är ett stort projekt att göra ensam, men jag är ihärdig.

Hårdvara
Ett Z-Turn devboard. En ZYNQ z7020, mest för att jag hade en tillgänglig. Kan ju också vara kul att lägga diverse hjälpfunktioner i FPGA-delen.
├ 2x ARM-A9 CPU.
├ 512MB DDR3.
├ Gigabit ethernet.
├ USB-host. Främst till extern lagring. Kanske fullt host-stöd senare om tid finns.
├ HDMI. Kanske. Systemet kommer primärt fjärrstyras via nätverket men det kan ju vara kul med lokal kontroll.
└ Kanske extern wifi. Jag har en microchip MRF24WB0MA som inte används till någonting men dokumentationen till den är väldigt dålig.

Mjukvara & dokumentation
Vivado webpack, med tillhörande mjukvaru-SDK. (usch, eclipsebaserat..)
Diverse datablad.
Google.


All kod tillhörande projektet kommer att laddas upp någonstans (github?) med en "gör vad du vill"-licens i de fall det är möjligt. Om jag måste använda tredjepartsbibliotek gäller givetvis deras egen licens.
Korta snuttar kan också komma att postas här i tråden med förklaringar om jag tycker det behövs (fråga gärna efter någonting om ni tycker att det fattas) men tanken är att tråden främst ska dokumentera utvecklingsprocessen och inte bara vara en koddump.

Första steget blir att skapa boot-kod (och lära mig ARM-assembler) för att få en processor i ett körbart läge (tvåkärnigt sparas till senare), och sen tända en LED för att visa att den lever.
Ingen bootloader ännu, kommer att starta över JTAG tillsvidare.

Fler uppdateringar följer..
Användarvisningsbild
Lennart Aspenryd
Tidigare Lasp
Inlägg: 12607
Blev medlem: 1 juli 2011, 19:09:09
Ort: Helsingborg

Re: Ett embedded-OS

Inlägg av Lennart Aspenryd »

Spännande!
Men den första reflexionen är! Jorden är färdig, man börjar om från början!
Men visst, det är säkert kul och mycket lärorikt, jag vill inte avstyra dig utan tipsar om boken!
http://libris.kb.se/bib/7272133
Sedan är väl Linus T memoarer nästa.
Men skumma Github så kanske du finner en själsfrände. Det är nog den bästa starten!
Användarvisningsbild
lillahuset
Gått bort
Inlägg: 13969
Blev medlem: 3 juli 2008, 08:13:14
Ort: Norrköping

Re: Ett embedded-OS

Inlägg av lillahuset »

"En dators födelse" borde alla med minsta intresse för datorer läsa. Eller ännu hellre på engelska, "The soul of a new machine".
Användarvisningsbild
hawkan
Inlägg: 2585
Blev medlem: 14 augusti 2011, 10:27:40

Re: Ett embedded-OS

Inlägg av hawkan »

Tänker du använda något befintligt som hjälp eller utgångspunkt eller är allt från scratch?
T ex kompilator finns det? Eller ska du skriva allt i assembler, huvaligen.
Mr Andersson
Inlägg: 1394
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: Ett embedded-OS

Inlägg av Mr Andersson »

hawkan, jag kommer använda gcc. Att skriva allt i assembler, det är lite väl mycket självplågeri. :)

Bootprocessen på en ZYNQ fungerar ungefär såhär (om jag minns databladet rätt, har det inte på den här datorn):

1) Vid power-on reset körs lite kod i en ROM som resettar alla peripherals
Beroende på status på bootpinnarna på SoC:n (utdragna som jumprar på utvecklingskortet) sker en av:
2a) Processorn stannar och väntar på koduppladdning via JTAG.
2b) ROM:en kopierar kod från flashminnet till RAM och lämnar över kontrollen.
2c) ROM:en letar efter "boot.bin" på sd-kortet (kräver dock FAT-filsystem), laddar till RAM och lämnar över kontrollen.
3) Min kod körs

2c tror jag inte jag kommer använda mig av då det kräver FAT, och de andra två alternativen tror jag är rätt lika mellan alla olika ARM-vendors så det borde gå att köra på andra tillverkares mcu:er också med relativt små ändringar.

Det som i punkt 3 måste göras i assembler är att rensa och starta L1 & L2 cache, starta DDR-kontrollern, samt konfigurera stacken. Sen kan resten skrivas i C(++). Normalt sker det här automatiskt via nånting som xilinx kallar "board support package" som länkas in vid kompilering. Jag hade tänkt försöka lösa det här själv utan att tjuvkika på deras kod, mest för att man lär sig inte så mycket på att bara kopiera. Men det finns ju kvar som alternativ om jag inte lyckas själv.

Eventuellt, beroende på hur stor OS-kärnan blir, måste jag dela upp den i flera delar och starta en liten "loader" som kopierar in resten till DDR-minnet då boot-RAM "bara" är 256KB. Har ingen koll så här tidigt i projektet hur långt det kommer räcka.

För användarprogrammen som OS:et ska köra hade jag tänkt använda ELF som binärformat då det är rätt så standard på nästan allt utom windows. libc måste skrivas om för att fungera med min os-kärna (minnesallokering, I/O, etc) och sen kan man, iaf teoretiskt, kompilera standardföljande C-kod. Med emulering av linuxkärnans syscalls borde man också kunna köra arm-linuxbinärer rakt av, men det ligger nog lång fram i utvecklingen, om ens alls.

Lasp, tack för boktipset. Såg att den fanns som ljudbok så då kan jag lyssna på den medans jag snickrar på mitt projekt. :D
Användarvisningsbild
Oskar
Inlägg: 1804
Blev medlem: 6 september 2005, 15:11:36
Ort: Storsjö, Sorsele

Re: Ett embedded-OS

Inlägg av Oskar »

Vilket spännande projekt. Att gå på djupet i det tekniska är verkligen intressant. En bättre förståelse för grunderna kan uppnås, intressant för oss andra också!
Användarvisningsbild
Gizmo
Inlägg: 1613
Blev medlem: 8 september 2009, 00:37:45
Ort: Göteborg
Kontakt:

Re: Ett embedded-OS

Inlägg av Gizmo »

Hmm. Jag vet inte varför men jag kommer direkt att tänka på Erlang, eller mer specifikt http://www.erlang-embedded.com/ och citatet:

Erlang is a programming language written with two principles in mind: “Errors will ALWAYS occur” and “The system must NEVER go down”.
Mr Andersson
Inlägg: 1394
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: Ett embedded-OS

Inlägg av Mr Andersson »

Efter mycket bråkande med bootprocessen bestämde jag mig för att använda stora delar av tillverkarens egen kod. Det är ca 500 rader assembler bara för att rensa cacharna, varav några register är helt odokumenterade. Nu kommer jag iaf så långt att main() körs.

Dags för mcu-varianten av hello world, en blinkande LED :) Här hade jag två val;
Det mer praktiska: Använda GPIO via processorns peripheral-register, eller
Det mer roliga: knyta en pinne till en minnesadress via AXI-bussen och lite HDL-kod.

Jag valde det roliga sättet. Sen spårade det snabbt ur. Det slutade med en tre-kanals PWM-kontroller för en RGB-led skriven i verilog. Nu kan jag kontrollera ljuset via att skriva till en minnesaddress likt så:

Kod: Markera allt

#define SET_RGB(r,g,b)   *(volatile u32*)RGB_ADDR = 0xFF000000 | (r << 16) | (g << 8) | b
SET_RGB(0, 255, 100);
RGB_ADDR_REG.png
https://github.com/mos-project/mos-core ... dl/PWMC.sv
PWM-kontrollern är den enda intressanta koden, resten är bara "glue logic" för att instansiera tre kontrollers och koppla dem till AXI-bussen så den är inte inkluderad. Men om nån vill ha tips på hur man kan göra så fråga gärna.


Sen har jag också jobbat lite på en minnesallokerare baserad på https://en.wikipedia.org/wiki/Buddy_memory_allocation
Skillnaden på en frame allocator och vanliga malloc() är att den arbetar med hela minnessidor, eller så kallade 'frames' (4kB), istället för med valfria allokeringsstorlekar. Tanken är att den ska användas för att allokera fysiskt minne som sen delas ut som virtuellt minne till userspace, som sen implementerar en egen malloc() för applikationer.

Buddy-systemet fungerar ungefär såhär:

Man startar med ett enda stort block som täcker hela minnesområdet.
Om någon vill allokera hela minnet, markera det som använt och sen är det klart.
Om någon vill allokera mindre delar, dela rekursivt blocket i två lika delar tills storleken blivit den minsta "power of 2" (vad heter det på svenska?) som täcker den begärda minnesstorleken.

Vid frigörning av minnet (som nu är en halva av ett större block) kollas om "kompisen" (därav namnet 'buddy allocator') också är ledig. Om båda är oanvända slås de ihop till ett större block igen. Sen kollas det större blockets kompis, osv.. När alla tidigare allokeringar frigjorts är man tillbaka på ett enda stort block igen.

Jag gjorde en animerad bild som kanske förklarar det lite tydligare.
I exemplet är totala minnesmängden 1MB och vi vill ha 64kB.
Vitt är ledigt minne, grått upptaget, och grönt det minnesblock vi till slut blir tilldelade.
frame_allocator.gif
Notera att bara för att 1024kB-blocket är markerat upptaget betyder det inte att allt minne är fullt, utan bara att det är slut på block av den storleken. Nästa allokering som görs kan alltså vara max 512kB.
https://github.com/mos-project/mos-core ... locator.cc

Nästa steg blir att konfigurera MMU:n för att få igång virtuellt minne.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
Magnus_K
EF Sponsor
Inlägg: 5854
Blev medlem: 4 januari 2010, 17:53:25
Ort: Skogen mellan Uppsala-Gävle

Re: Ett embedded-OS

Inlägg av Magnus_K »

Det här är så häftigt så hälften vore nog.
Datadyslektiker som jag är så kan jag tyvärr bara önska dig lycka till :bravo:
Följer vidare och ser fram emot att läsa om framstegen.
Henke_83
Inlägg: 227
Blev medlem: 20 oktober 2007, 09:17:41
Ort: Ekerö
Kontakt:

Re: Ett embedded-OS

Inlägg av Henke_83 »

Spännande projekt - intressant att följa.
Säger lycka till :tumupp: :)
MiaM
Inlägg: 9903
Blev medlem: 6 maj 2009, 22:19:19

Re: Ett embedded-OS

Inlägg av MiaM »

Kul++ projekt! :tumupp: :tumupp:

Lite förslag!.
Mr Andersson skrev: ├ SSL/TLS, kanske IPSec. Osäker på om SSL ska räknas till nätverkssystemet eller ligga på en högre nivå.
└ Kanske NFS och/eller SMB. (Ska det tillhöra filsystemet eller nätverket?)
Behöver det specas upp vad det exakt tillhör?

Jag har inte riktigt läst på hur OS/9 gör men de verkar ha tagit "allt är filer" så långt det går. Om man struntar i det och istället tänker "allt är överföring av data" så är det väl rätt enkelt att t.ex. NFS/SMB å ena sidan pratar med nån slags grundläggande API för att skyffla data över nätverket, och å andra sidan exponerar ett annat API för att skyffla data till/från applikationer i filform.

SSL och liknande kan med fördel ligga som ett lager ovanpå TCP. (Ja, eller om nån nu använder sånt för UDP så låt det köra där med för all del).

Jag föreslår ett såpass gemensamt API som möjligt för alla sätt att överföra mängder av data, och ett sätt att presentera sökvägar som kan peka på allt som går att överföra som data. Jämför hur gamla MS-DOS har CON, AUX, LPT1, COM1 o.s.v. som "filer" som går att öppna med samma API:er som man använder till filer, och jämför hur *ix har /dev/.. för att accessa olika former av enheter. Ordna nätverket på ett liknande sätt och låt tcp-koppel och udp-"koppel" utgöra strömmar på samma vis. DNS-uppslag kan se ut som symlänkar till IP-adresser. Bygg gärna in stöd för att länka på hanterare för filer som inte finns i filsystemet, så kan motsvarigheten till hårdkodade saker i hosts-filen ligga som faktiska symlänkar i diskfilsystemet medan när något efterfrågas som inte finns färdigt på detta sätt så görs dns-fråga. Även listning av kataloger bör kunna trigga en hanterare som gör uppslag i kataloger, t.ex. om du har SMB så skulle den kunna fråga nätverket vilka kända maskiner det finns på SMB-nätet. En flagga till APIer/kommandon som listar filer skulle kunna styra om denna uppslagning ska göras eller inte, och motsvarande för att öppna filer (för att slå av kataloglistning via nätverket respektive dns-uppslag för att vissa nätverksfunktioner ska kunna tidsbegränsas).

Låt det finnas en allmän timeout som kan skickas som parameter till allt som i något teoretiskt scenario kan time:a ut.

Gör så att allt går att "vänta" på.
Mr Andersson
Inlägg: 1394
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: Ett embedded-OS

Inlägg av Mr Andersson »

Tack för synpunkterna.

> Behöver det specas upp vad det exakt tillhör?

Nä, egentligen inte. Från ett tekniskt perspektiv spelar det ingen roll alls. Jag tänkte mer från ett användarperspektiv var det ska ligga i API:na och dokumentationen. Men det går ju att flytta i efterhand så det är inte så noga just nu.

Min tanke just nu är att om en applikation t.ex. öppnar en tcp-anslutning får man tillbaka ett id från nätverks-API:et som är unikt för den appen, och sen kan man använda vanliga fil-funktioner för att läsa och skriva (något prefix)/net/<id> med t.ex. fread, fwrite, std::fstream, etc.
Jag hade tänkt mig någonting liknande /dev där program kan registrera olika hanterare, antingen globalt eller bara för sig själv beroende på användarbehörighet, men att göra det för kataloger också är en bra idé som jag inte hade tänkt på.

> Låt det finnas en allmän timeout som kan skickas som parameter till allt som i något teoretiskt scenario kan time:a ut.
> Gör så att allt går att "vänta" på.


Det blir inga blockerande väntningar alls utan allt som går ska bli asynkront, dvs programmet registrerar callbacks som anropas när API:na körts klart, eller en felhanterare om tiden går ut.

Det har inte blivit några uppdateringar här på ett tag nu för jag har haft lite fritid plus att jag fastnade ett tag pga bristfällig dokumentation. Jag ville försöka lista ut vad en del odokumenterade register gör som deras egen kod använder men till slut gav jag upp och får nog acceptera att vissa saker ska vara hemliga för oss som inte är nog stora för att få tillgång till intern dokumentation.
Det som hänt sen sist är att jag gjort en UART-drivrutin och en halvfärdig MMU-drivrutin. Virtuellt minne fungerar men inte minnesskydd.
Skriv svar