Jump to content
  • Sky
  • Blueberry
  • Slate
  • Blackcurrant
  • Watermelon
  • Strawberry
  • Orange
  • Banana
  • Apple
  • Emerald
  • Chocolate
  • Charcoal

Solra Bizna

Members
  • Content Count

    90
  • Joined

  • Last visited

  • Days Won

    8

Posts posted by Solra Bizna

  1. The "Enhanced" Apple IIe did. The others, as with earlier Apples, used a plain old NMOS 6502. The 65C02 is the CMOS version of the processor. It's largely compatible with the NMOS one, but has more instructions, fewer bugs, and draws less power at high clock speeds. Most of the undocumented instructions of the NMOS processor became documented no-ops, breaking the programs that relied on them. Apple BASIC should be compatible; someone should try to load it up...

    I forgot to mention in the OP that I specifically emulate the Western Design Center version of the chip, so it has the RMB*/SMB*/BBR*/BBS* instructions. While I was programming the BIOS, those quickly became my favorite instructions in the whole set.

  2. Since I had to write a 65C02 emulator core for work anyway, and since there is still a distinct lack of finished "real CPU" architecture modules for OpenComputers, I just spent the last couple weekends making one. All features that have been tested work, though the testing has not been very thorough.

    The Minecraft 1.7.10 version can be found here, and the (very dry) documentation for both the hardware and the BIOS is here. It should build for later Minecraft versions with only minor modifications; I built it for 1.7.10 because that's the version I use. (Source code is on GitHub.)

    Please report bugs on the GitHub issue tracker, though don't be surprised if it takes me a while to respond there (GitHub notifications aren't working for me). Feel free to poke me on IRC; SolraBizna on irc.esper.net or irc.tejat.net.

    Features

    • Total control over memory usage 
    • Fully persistable
    • Technically supports almost 32MiB of main memory through the MMU*
    • Non-maskable watchdog timer
    • Interrupts occur on signal delivery, allowing interrupt-based signal handling
    • Straightforward memory mapped interfaces for disk drives, redstone, and battery
    • "Serial terminal" allows basic, simple screen-and-keyboard based UIs
    • Support via UIF for all components accessible from Lua, including userdata support
    • Standard BIOS
      • Very basic interactive debugger, can load S-records either pasted or manually entered
      • Bootloader can boot S-records and binary images from managed and unmanaged drives
      • Basic signal handling for keyboard input, including a blinking cursor
      • Can selectively turn on/off BIOS features from booted code
    • User Mode (barely tested) allows memory protection, multitasking—even total virtualization with some work
    • Sync safe (only with a deadline setting of 10ms or so)
    • The CPU has around 512 bytes of built-in memory, allowing simple programs to run without any RAM modules

    *If you dial up the memory amount high enough, you may get disconnection errors due to an oversight in OpenComputers' API. This will hopefully be fixed soon, whether through a workaround in OCMOS or a change to OpenComputers. Memory modules are, by default, smaller than those for Lua computers; in my own testing with two tier 3.5 memory modules (256KiB), I did not experience any disconnects. Meanwhile, since the 65C02 can do so much with very limited memory, you shouldn't experience any serious problems.

    Version History

    0.5.2

    • Architecture now has NoMemoryRequirements annotation, allowing you to build microcontrollers, drones, and robots without memory modules if all you need is the stack and zero page.
    • WAI no longer spins pointlessly, and now reduces host CPU usage when called.
    • Now, by default, if runThreaded runs for longer than one second without meeting the cycle budget, it will give up on doing so and briefly sleep. This prevents degenerate MMU slowdowns from ruining a world or server.

    0.5.1

    • Works on the server now. (The LAST change I made before releasing 0.5 broke this.)
    • biosOptional option means you get the Standard BIOS even if no EEPROM is installed. This is slightly cheaty, but since there's not a crafting recipe for the Standard BIOS yet...

    0.5.0

    • Initial release
  3. I edited it to remove the 4-byte padding from the binary boot records. My reasoning is that, on IO port heavy 8-bit architectures (such as OCMOS), tracking the current position and skipping a specified number of bytes is clumsier than just reading until the NUL; whereas on alignment-sensitive architectures, it's not terribly difficult to do an unaligned read "by hand".

    1. Cross-Architecture Booting
    2. Universal Interchange Format
    3. OpenComputers Ethernet (reserved by myself)
    4. OCranet family of protocols: OCR (OCranet Relay)
    5. OCranet family of protocols: NNR (Network-to-Network Routing)
    6. Global Empire Routing Technology
    7. ON2 - Simple L2 protocol for network stacks
    8. Allocated Network Card Port Numbers (reserved by MajGenRelativity)

    If you'd like to reserve an OETF document number, contact me, as I appear to have become the central authority for them. Here are the ways in which I can be contacted, in descending order of how quickly I will see your request:

    • SolraBizna on IRC (irc.tejat.net, irc.esper.net)
    • solra@bizna.name via email
    • Private message on these forums

    If you catch me at a good time, I'll have a few things to suggest on the topic of your document. If you catch me at a bad time, I'll probably just reserve you a number without question. :)

  4. On 2/23/2017 at 9:40 AM, feherneoh said:

    I see that occross can build the compiler for OC-ARM Little-Endian too. Does the mod actually support switching endianness and Little-Endian binaries?
    I have a project that I simply cannot get to compile as Big-Endian, as I cannot figure out which linker script stays still armel after reconfiguring everything I found as armeb

    Sure does. Just two things to keep in mind:

    • The CPU boots in big-endian mode, so you'll want to do SETEND LE as your first instruction. I'm not certain, but it might switch to big-endian mode on interrupts as well. (Not that it matters, since my interrupt code is just stubs...)
    • boot0 will only load big-endian ELFs. It should be (relatively) simple to make a little endian version: do SETEND LE as the first instruction, manually byte swap the constants/shifts wherever boot0 uses a 32-bit integer comparison to test 4 bytes of memory, and remove the code that checks for the BE8 flag.

    I'd planned to modify boot0 to be able to load either little- or big-endian ELFs, and switch the endianness itself. Of course, I'd also planned to make it OETF-compliant, and to finish the mod in general. If only I still had the time...

  5. THIS IS A DRAFT. It may change before becoming "official". Please feel free to suggest breaking changes.
    Abstract

    This document provides a binary interchange format, intended primarily to support generic component IO.

    Rationale

    OpenComputers' component bus is designed for high-level languages. It sends and receives groups of dynamically typed values. It is intended to be user-friendly and self-discoverable, and it has largely achieved this goal. However, with low-level architectures, there is no obvious, straightforward way to represent these values. This document aims to provide a standard representation, freeing individual architects from having to devise their own representations, and minimizing unnecessary differences between architectures.

    Every value that can be sent over an OpenComputers bus can be represented as described in this document, and (barring length restrictions) vice versa.

    Conventions

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

    All signed integers are two's-complement.

    Concepts

    • Tag: Gives the type of a subsequent Value.
    • Value: Data whose structure and meaning depend on its type.
    • Tagged Value: A Tag, followed by a Value of the indicated type.
    • Producer: A program or process that generates data in this format.
    • Consumer: A program or process that consumes data in this format.
    • Packed mode: A representation designed to occupy very little space.
    • Unpacked mode: A representation designed to be easy to manipulate on 32-bit architectures.

    Tags

    A type tag denotes the type of a subsequent Value. In Packed mode, the tag is a 16-bit signed integer. In Unpacked mode, it is a 32-bit signed integer, aligned to a 4-byte boundary.

    Values

    String (UIFTAG_STRING = 0x0000–0x3FFF = 0–16383)

    A UTF-8 code sequence. The tag provides the length, in bytes, of the sequence. Producers MUST NOT generate invalid code sequences, including "modified UTF-8" conventions such as non-zero NUL and UTF-8 encoded surrogate pairs. Producers MUST NOT arbitrarily prefix strings with a spurious U+FEFF BYTE ORDER MARK. Consumer handling of invalid code sequences is undefined.

    If a Consumer encounters a String where a Byte Array is expected, the Consumer MAY incur a round-trip conversion to its native string type. This may mean that the bytes the Consumer actually sees differ from the original bytes where invalid code sequences occur.

    Consumers MUST handle NUL bytes in a String in an appropriate manner. Consumers MUST not assume that Strings are NUL-terminated—they are not.

    In Unpacked mode, additional zero bytes MUST be added to the end of the String, so that a subsequent Tag will be aligned to a 4-byte boundary.

    Byte Array (UIFTAG_BYTE_ARRAY = 0x4000-0x7FFF = 16384-32767)

    An arbitrary sequence of bytes. The tag, minus 16384, provides the length in bytes of the sequence.

    If a Consumer encounters a Byte Array where a String is expected, the Consumer MUST interpret the Byte Array as if it were a String of the given length.

    In Unpacked mode, additional zero bytes MUST be added to the end of the Byte Array, so that a subsequent Tag will be aligned to a 4-byte boundary.

    End (UIFTAG_END = 0x...FFFF = -1)

    A special tag signifying the end of an Array or Compound.

    Null (UIFTAG_NULL = 0x...FFFE = -2)

    Absence of a value. Equivalent to null and nil in various programming languages.

    (Note: there is no tag -3.)

    Double (UIFTAG_DOUBLE = 0x...FFFC = -4)

    A 64-bit IEEE 754 floating point value. Consumers that encounter a Double where an Integer is expected MAY fail. Producers that are producing a Double which has an exact Integer representation SHOULD produce that Integer instead.

    Integer (UIFTAG_INTEGER = 0x...FFFB = -5)

    A 32-bit signed integer. Consumers that encounter an Integer where a Double is expected MUST convert the Integer to a Double.

    Array (UIFTAG_ARRAY = 0x...FFFA = -6)

    A series of Tagged Values, in a particular order, terminated by an End.

    Compound (UIFTAG_COMPOUND = 0x...FFF9 = -7)

    A series of pairs of Tagged Values. The order of the pairs is not significant. Each pair consists of a Key and a Value, in that order. A Key may be any type except a Byte Array, a Null, an Array, or a Compound. A Value may be any type. The list is terminated by an End. If a Consumer encounters an End as the second element of a pair, the result is undefined.

    UUID (UIFTAG_UUID = 0x...FFF8 = -8)

    A 128-bit RFC 4122 UUID. Regardless of endianness, the bytes are in display order. Consumers that encounter a UUID where a String is expected MUST convert the UUID to its canonical string representation, in lowercase. Producers and Consumers alike should take note that a random sequence of bytes is not necessarily a valid UUID.

    True (UIFTAG_TRUE = 0x...FFF7 = -9)

    A boolean true value.

    False (UIFTAG_FALSE = 0x...FFF6 = -10)

    A boolean false value.

    TODO

    This document is incomplete. Still to be written: recommendations on endianness and packing, useful common optimizations.

  6. THIS IS A DRAFT. It may change before becoming "official". Please feel free to suggest breaking changes.

    Abstract

    This document provides guidelines for dealing with EEPROMs and locating architecture-specific boot code.

    Rationale

    OpenComputers supports a wide variety of architectures. Even more so than in the real world, OpenComputers architectures can differ dramatically from one another. Some architectures run programs in a particular high-level language directly, while others simulate real or fictitious low-level ISAs. Some architectures natively deal with data in 8-bit units, while others have built-in advanced string handling and vector processing capabilities.

    In contrast with this variety, OpenComputers components have a standard interface. An EEPROM containing boot code can easily end up being used on the "wrong" architecture, to say nothing of boot disks.

    This standard aims to solve that problem, by providing architecture-aware guidelines for dealing with EEPROMs, and procedures for locating boot code on filesystem-based and sector-based boot media. It aims to be simple to implement on the widest possible variety of architectures.

    Conventions

    Unless otherwise specified, all references to text imply 7-bit ASCII codes. Behavior on encountering bytes with the high-bit set is undefined.

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

    Architecture Identifier

    Each architecture must provide a unique, preferably meaningful identifier which is specific to that architecture. This is the Architecture Identifier, or AID. The AID SHOULD be the same as the Architecture.Name annotation for the architecture, which is usually the same as the name used in the tooltip of the CPU.

    An AID MUST contain no bytes other than the following characters: digits, upper and lowercase letters, periods (.), dashes (-), underscores (_), slashes (/), spaces. In addition, an AID MUST NOT begin with a space, end with a space, or contain a run of two or more spaces. An AID SHOULD begin with a capital letter, if for no other reason than to make boot code easier to tell apart from other files and directories in listings.

    A new AID SHOULD NOT contain spaces, unless it is required for compatibility.

    An architecture with multiple variants that are mutually incompatible SHOULD use different AIDs for each variant. Fallback schemes, such as one where multiple AIDs are tried, are architecture-specific and outside the scope of this document.

    CAB-aware EEPROM images ("CABE images")

    This section applies to architectures, EEPROM flashing utilities, and any hardcoded boot code (analogous to machine.lua in the "standard" Lua architecture).

    A CAB-aware EEPROM image (a "CABE image") MUST begin with "--[", followed by zero or more "=", followed by "[CABE:". This is the prefix string. A CAB-compliant architecture MUST be prepared to deal with any number of "=" between 0 and 7, and a CABE image SHOULD NOT use more than 7.

    The prefix string is followed by a single AID. This denotes the "intended architecture" for this CAB image. This is followed by one of two things:

    • A colon (:), in which case the "main body" consists of the bytes following the colon, up until a valid suffix string is encountered.
    • A suffix string, in which case the "main body" consists of the entire remainder of the image, and MUST be valid Lua 5.2 AND Lua 5.3 code.

    A "suffix string" consists of an ASCII "]", followed by the same number of "=" as were in the prefix string, followed by another "]". In order to be a valid suffix string, it MUST contain precisely the same number of "=" as the prefix string contains. In particular, an otherwise valid suffix string that contains more "=" than the prefix string MUST be treated exactly the same as any other non-suffix-string byte sequence.

    The "main body" contains the actual EEPROM data for that architecture. The interpretation of this data is architecture-defined.

    If a CABE image contains data after a valid suffix string, that data MUST be Lua code which is cross-compatible between the Lua 5.2 and 5.3 architectures provided by OpenComputers. If this is not the intended architecture of the CABE image, this code SHOULD consist solely of an informative error call.

    Any deviation whatsoever from this standard results in a non-CABE image. All handling of non-CABE images is architecture-specific, but a non-CABE image SHOULD be treated however the "main body" of a valid CABE image would be treated.

    The preferred file extension for CABE images is ".cabe". The preferred MIME type is "application/x-cabe-image", though "application/octet-stream" is acceptable. CABE images MUST NOT be distributed using any "text/*" MIME type, as doing so will almost certainly corrupt binary CABE images.

    Here is an example CABE image targeting a fictional architecture:

    --[[CABE:HyperTalk:
    ask "What is your name?"
    answer "Hello," && it & "!"
    ]]
    error"HyperTalk architecture required"

    And here is one targeting a built-in Lua architecture:

    --[[CABE:Lua 5.2]]
    for n=1,5 do
      computer.beep(2000, 0.1)
    end

    EEPROM-based transparent architecture switching

    A future OpenComputers release may add support for transparent architecture switching, through additional NBT data for EEPROMs. It is expected that this will consist of a single AID identifying the architecture the EEPROM is designed for. This section applies in the event of such support becoming available. To provide consistency to users, architectures SHOULD NOT attempt to implement any form of automatic architecture switching themselves.

    An EEPROM flashing utility SHOULD attempt to parse all images as CABE images. If successful, it SHOULD tag the EEPROM appropriately and burn only the "main body". Otherwise, it SHOULD remove any existing architecture tag from the EEPROM and burn the entire image.

    An architecture booting an EEPROM with a valid architecture tag SHOULD NOT also attempt to parse it as a CABE image. An architecture booting an EEPROM with no valid architecture tag SHOULD attempt to parse it as a CABE image, and MUST NOT affix an architecture tag itself.

    Boot code

    This section applies to EEPROMs intended as first-stage bootloaders, as well as programs intended to be booted by such EEPROMs.

    Bootloaders SHOULD, if the boot EEPROM contains a boot device UUID, attempt to boot from that device first. A boot EEPROM contains a boot device UUID if eeprom.getData() consists entirely of an ASCII UUID, or if it begins with an ASCII UUID followed by a null byte.

    Managed mode (filesystems)

    Bootloader behavior on managed filesystems:

    • If "/<AID>" exists and is a directory, boot "/<AID>/boot".
    • If "/<AID>" exists and is a file, boot "/<AID>".
    • Any further cases are architecture-specific.

    If one of the above conditions are met, but its booting attempt fails, the booting process MUST NOT continue automatically. For instance, if "/<AID>" is a directory but booting "/<AID>/boot" fails, the bootloader MUST either fail with an error, or prompt a user for further action.

    Exactly what "booting" entails is architecture-specific. On a Lua architecture, it consists of loading a file as Lua code and then executing it. On low-level architectures, it might consist of loading a file's contents to a fixed RAM address and jumping into it. Architectures SHOULD provide a standard way for the first-stage bootloader to tell the booted code the UUID of the filesystem it was loaded from.

    Example: Consider a boot on the OC-ARM architecture. The bootloader checks if "/OC-ARM" exists. It does exist, and is a directory. The bootloader then attempts to boot "/OC-ARM/boot". It fails, because "/OC-ARM/boot" is not valid. It crashes the machine with an error message explaining the problem.

    Unmanaged mode (drives)

    A CAB-compliant bootable disk begins with a boot sector. This boot sector MUST be the first or second sector of the drive. If both the first and second sectors contain a valid boot sector, only the first one will be used. A boot sector begins with the ASCII string "CAB", followed by zero or more text boot records. This list of text records is terminated with an exclamation mark. If this exclamation mark is followed by the particular byte sequence {0x00, 0x1A, 0xCA, 0xBD} (null byte, CP/M end-of-file marker, two-byte magic number), then it is followed by zero or more binary boot records, terminated by a null byte.

    Boot records MUST NOT extend past the end of the boot sector. Architectures MAY specify that boot records for that architecture must be text or must be binary, and MAY specify that binary boot records must be a particular endianness and/or must be sector-aligned. Bootloaders for architectures that do not specify that boot records must be text or must be binary MUST support both.

    A text record matches ":<AID>=<offset>+<length>". <AID> is the AID for which the code is intended. <offset> is a decimal number, giving the byte offset at which to begin reading, OR "s" followed by a decimal number, giving the sector number at which to begin reading. <length> is a decimal number giving the number of bytes to read.

    A binary record is described by the following C99 structure:

    struct {
      uint8_t record_length;
      uint8_t flags;
      uint16_t load_start;
      uint32_t load_length;
      char aid[];
    };

    record_length is the number that must be added to the offset of this record to skip it. It MUST be equal to 8 + AID length + 1.

    flags is a bitfield. The following flags are defined:

    • 0x40: If set, load_start is a sector number. If clear, load_start is a byte offset.
    • 0x80: If set, load_start and load_length are little-endian. If clear, load_start and load_length are in network byte order (big-endian).

    load_start is either a sector number or a byte offset to begin the loading process at. load_length is the number of bytes to read. aid is the AID of the intended architecture, and MUST be null-terminated.

    As with managed mode, exactly what is done with the loaded data is architecture-specific. Bootloaders that only support binary records should consider a sector to be a valid boot sector if it begins with "CAB", and locate the end of the text boot records without parsing them by searching for the first "!". Bootloaders that only support text records need not consider any bytes past the first null byte. A boot sector that contains no records is valid, and MUST prevent any attempt to read possible subsequent boot sectors.

    Example 1:

    CAB:Lua 5.2=s3+17:Lua 5.3=s3+17:HyperTalk=384+5100!
    (followed directly by binary data:)
    001A CABD (valid binary records follow)
    0F (the length of the first record)
    C0 (little-endian, sector offset)
    0900 (start at sector number 9)
    0000 0100 (load 65536 bytes)
    5342 3635 3032 00 (null-terminated string "SB6502")
    00 (no more binary records)

    This drive contains valid boot code for Lua 5.2, Lua 5.3, HyperTalk, and SB6502. Lua 5.2 and 5.3 both use the same boot code, which is 17 bytes long and starts at the beginning of sector number 3. The HyperTalk boot code is 5100 bytes long and starts 384 bytes into the disk, which, when using 256-byte sectors, is halfway through the second sector. The SB6502 boot code is 65536 bytes long and starts at the beginning of sector number 9.

    Example 2:

    CAB!

    This is a valid boot sector, but contains no boot records.  This is the safest way to mark a drive as non-bootable.

  7. On 8/24/2016 at 3:53 PM, GreaseMonkey said:

    ...converting decimal strings to integers is pretty difficult on a 6502, actually.

    It's a pain, certainly. It doesn't require a general-purpose multiply, though. Multiplying by 10 just involves two two-bit shifts and two adds.

    On 6/13/2016 at 10:43 AM, TYKUHN2 said:

    It would probably save a few lines of code and space if you used an byte offset instead of a sector.

    Division is much harder on some architectures than others; using sector offsets makes things much easier on those architectures. Adding a division routine could easily make the bootloader no longer fit into ROM. (Correct me if I'm wrong, but I was under the impression that the sector-based read code takes a sector number, not a byte offset. Also, the sector size may change between different configurations or different devices, so it can't be hardcoded.)

    On 8/24/2016 at 3:53 PM, GreaseMonkey said:

    I get the feeling it would be better to have a text string for architectures which handle text strings well, which then ends in a \n (10, 0x0A) and a \x00 (0, 0x00). Following that should be a binary format.

    Or heck, this would be better:

    
    BOOT:Lua 5.2,Lua 5.3:512+1199\n
    BOOT:MikeKaraoke:64+102\n
    \x00(pad up to next 16-byte boundary w/ \x00 bytes, then binary data follows:)
    
    uint8_t magic; // 'B' for big-endian, 'b' for little-endian, 0x00 to terminate the boot list
    uint8_t block_length; // measured in 16-byte units
    uint16_t length; // measured in bytes
    uint32_t offset; // measured in bytes where the first byte of the disk is 0
    uint8_t archname[]; // NUL-terminated string
    
    {'b', 1, 2472, 3072, "OC-ARM"},
    {0x00, ...}
    
    After all that: \x00

    Alternatively, have binary boot records on sector 1, and text boot records on sector 0, which would be even better.

    I definitely like the idea of separate text and binary boot records. Different architectures are likely to have radically different capabilities in terms of text processing vs. binary processing. Some bootloaders/architectures could indicate that they only respect one or the other; a JavaScript architecture might only respect text boot sectors, for example, while a 6502 architecture might only respect binary boot sectors.

    I'll write up a new proposal soon.

    (Also, I have now learned an important lesson about how the subscription system on this forum works. I have a temporary glut of free time, so we'll see what happens.)

  8. Is there any way to sleep until a signal is pushed? Atm I am using this:

    #define pullSignal(buffer) asm volatile(\
    	"1:\n\t"			\
    	"STC p3, c0, %0\n\t"	\
    	"BVS 1b \n\t"		\
    	::"m"(buffer))
    
    to wait for a signal but when I do that the emulator starts using 70% of my cpu while running. I tried using "MRC p3, 0, r0, cr2, cr0" like you do in the tetris but that gives same amount of lag.
    The lag (if you're talking about the latency between causing a signal and having the program "receive" it) is a side effect of the way OpenComputers syncs with Minecraft. The simulator is simulating it accurately(ish). Doing a tight loop to wait for a signal will reduce the lag in the simulator but will increase it in Minecraft.

     

    Also would it be easy to link libc so I can use strcmp and such? I tried linking the compiled objects in newlib but it gives the error

    arm-none-eabi-ld: error: ../newlib-jarm-build/libc/string/lib_a-strcmp.o uses VFP register arguments, bin/test.elf does not
    arm-none-eabi-ld: failed to merge target specific data of file ../newlib-jarm-build/libc/string/lib_a-strcmp.o
    
    would it work if I downloaded the GNU libc source code and compiled it with the same clang arguments?
    Getting GNU libc compiled for this target would probably not work at all, and then use too much memory if it did. The Lua source code theoretically shows the proper way to link with the compiled newlib, but I haven't released it yet (because it's still broken and I'm lazy).

    Here are some snippets that should get you on the right track getting newlib working:

    cd newlib-jarm-build
    ../newlib-2.4.0/newlib/configure --target arm-none-eabi --disable-multilib --disable-newlib-register-fini --disable-newlib-mb --disable-newlib-wide-orient --enable-lite-exit --disable-newlib-iconv --disable-newlib-supplied-syscalls --prefix=`pwd` CC="clang" CFLAGS="-g -target armv7a-eabi -march=armv7-a -mfloat-abi=hard -mbig-endian -mhard-float -mfpu=vfpv4 -mhwdiv=thumb,arm -ccc-gcc-name arm-none-eabi-gcc"
    make -k
    # this will error, THIS IS NORMAL
    Flags to compile with:

    ASFLAGS=-march=armv7-a -mfloat-abi=hard -mfpu=vfpv4 -EB -meabi=5
    TARGET_FLAGS=-target armv7a-eabi -mbig-endian -mfloat-abi=hard -mhard-float -mfpu=vfpv4 -mhwdiv=thumb,arm -D__ELF__
    CFLAGS=$(TARGET_FLAGS) -Oz -g -nostdlibinc -isystem include/ -isystem ../newlib-jarm-build/ -isystem ../newlib-2.4.0/newlib/libc/include/ -Wall -Werror
    LDFLAGS=--be8 -z max-page-size=4 -nostdlib -L../newlib-jarm-build -L../jarmrt/lib --no-enum-size-warning
    LIBS=-lm -lc -lbuiltin
    ARFLAGS=rs
    You'll need to write some stubs... here's sbrk:

    #include <unistd.h>
    #include <errno.h>
    
    extern uintptr_t ram_bytes;
    extern unsigned char __heap_start;
    
    void* sbrk(ptrdiff_t increment) {
      static uint8_t* cur_heap_end = ((uint8_t*)&__heap_start);
      if((uintptr_t)(cur_heap_end + increment) > ram_bytes) {
        errno = ENOMEM;
        return (void*)-1;
      }
      else {
        void* ret = cur_heap_end;
        cur_heap_end += increment;
        return ret;
      }
    }
    gettimeofday plugged into real time:

    #include <sys/time.h>
    
    int gettimeofday(struct timeval* tv, void* tz) {
      long long millis;
      asm("MRRC p3, 0, %0, %H0, cr1":"=r"(millis);
      tv->tv_sec = millis / 1000;
      tv->tv_usec = (millis % 1000) * 1000;
      return 0;
    }
    I can't remember whether I released jarmrt. I think I didn't yet because I hadn't sorted out license issues; it's an incredible hack that includes huge chunks of compiler-rt verbatim.
  9. It currently requires command line arguments. At the minimum, an argument pointing to the EEPROM image to use.

    Arguments I used when testing Tetris:

    -rom /home/sbizna/jarmrom/bin/tetris.rom -screen 2
    Arguments I used when testing the Lua interpreter:

    -rom /home/sbizna/jarmrom/bin/boot0.rom -screen 2 -memory 1024 -fsro /home/sbizna/nobackup/openos_floppy/ -fsrw /home/sbizna/nobackup/lua_test_disk/ -addrinfocmd "arm-none-eabi-addr2line -spfe /home/sbizna/luajarm/bin/lua52.elf.unstripped"
    If you run it without any arguments, it'll print a usage string giving the meanings of all the arguments.
  10. I build the simulator using Eclipse, but the project is not included. (I am not at all comfortable with blindly committing the huge array of cache files and metadata files and such that come with an Eclipse project. I can't prove to my satisfaction that I wouldn't be inadvertantly commititng something covered by an NDA.)

    It should be pretty easy to set up an Eclipse project to build it. Exclude the ocarm folder (right click it and "close", or something) and set the launch class to name.bizna.ocarmsim.OCARMSim.

    Edit: You'll also need to add the OpenComputers API to the build path in order for it to build.

    In any case, you don't have to build it yourself to use it. There should be a working .jar of the simulator under Releases.

  11. The Lua architectures boot a built-in "machine.lua", which boots "/init.lua". OC-ARM's (non-built-in) boot0 used to boot "/boot/arm.elf", but this was changed to "/OC-ARM" for three reasons:

    • Compatible with OpenOS (which would try, and fail, to run "/boot/arm.elf" as Lua code on startup)
    • No conflict with OpenArms (or other ARM architectures)
    • Similar to standard practice for OS kernels (/mach_kernel, /vmlinuz, /kernel...)
    Naturally, more advanced bootloaders will include ways of specifying alternate boot targets, but it makes sense to have a standard process for determining the default on a given architecture. I'd propose that the "standard default" be "/<arch-name>" where <arch-name> is a unique, short name for the architecture in question. (Generic names like "ARM" or "MIPS" should be avoided in favor of specific names like "OC-ARM" and "OCMIPS" and "OpenArms".) Whether this is an ELF file or whatever else would be architecture-specific.

    That's all well and good for filesystem-based booting, but what about drive-based booting? For that, I propose that the first sector of a bootable drive begin with a block in a format like the following:

     

    BOOT:Lua 5.2,Lua 5.3:s1+1199;OC-ARM:s6+2472;MikeKaraoke:b64+102.
    
    The meaning of this particular block would be "Lua 5.2 and Lua 5.3 compatible code starts at sector 1, and is 1199 bytes long. OC-ARM compatible code starts at sector 6, and is 2472 bytes long. MikeKaraoke compatible code starts at byte 64 of the boot sector (which is right after this block), and is 102 bytes long." (Most drives would only be bootable for one architecture.) This syntax is potentially extensible, depending on the details of the specification. Bootable code would be required to either start on a sector boundary or be contained entirely in the first sector. Under these circumstances, the bootloader can account for the raw sector size fairly simply, even where division is prohibitively expensive. The text parsing required is also fairly simple, even on an 8-bit architecture like the 6502.

    This idea is compatible with any partition table scheme of the "data at end of sector" type, like the MBR scheme.

    (Here I have assumed that the first sector is numbered 0. If the sectors are 1-based, the spec will have to be changed to reflect that.)

    I'd be happy to write all this up as a (pair of?) pseudo-RFC but I'm open to feedback first. I've heard that this topic has been discussed a lot on IRC.

  12. The only downside of that is that the "flash" utility would have to prompt for that information (user error party!), or it would have to be stored in the ROM file some other way. I'm open to it, though.

    Perhaps something like my original proposal as the storage format, and the "flash" utility can recognize that, strip it, and tag the EEPROM? ROM images that aren't tagged would default to "Lua 5.2;Lua 5.3" for obvious reasons.

    Maybe something like:

     

    arch=Lua 5.2;Lua 5.3
    Blah blah blah
    and after "flash" is done with it, the EEPROM only contains "Blah blah blah" and has its architecture tag set to "Lua 5.2;Lua 5.3".

    I like any solution that enables auto-switching of architectures, and at the same time I don't. (I think like wins out, though.)

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use and Privacy Policy.