{"id":25413663,"url":"https://github.com/ef15c/omsp","last_synced_at":"2025-04-22T11:59:33.028Z","repository":{"id":277677052,"uuid":"933175909","full_name":"ef15c/omsp","owner":"ef15c","description":"Oberon toolchain for MSP430","archived":false,"fork":false,"pushed_at":"2025-04-19T12:38:22.000Z","size":1260,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-19T17:30:36.202Z","etag":null,"topics":["compiler","linker","linux","msp430","msp430g2553","oberon","oberon-07","oxford-oberon","toolchain"],"latest_commit_sha":null,"homepage":"","language":"Modula-2","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ef15c.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-15T10:35:05.000Z","updated_at":"2025-04-19T12:38:25.000Z","dependencies_parsed_at":"2025-02-15T11:28:42.526Z","dependency_job_id":"11e154a5-97f1-4989-a115-cbfe72a8ca9c","html_url":"https://github.com/ef15c/omsp","commit_stats":null,"previous_names":["ef15c/omsp"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ef15c%2Fomsp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ef15c%2Fomsp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ef15c%2Fomsp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ef15c%2Fomsp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ef15c","download_url":"https://codeload.github.com/ef15c/omsp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250237833,"owners_count":21397400,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compiler","linker","linux","msp430","msp430g2553","oberon","oberon-07","oxford-oberon","toolchain"],"created_at":"2025-02-16T14:21:22.913Z","updated_at":"2025-04-22T11:59:33.018Z","avatar_url":"https://github.com/ef15c.png","language":"Modula-2","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MSP430 Oberon compiler\n## Differences from previous version\nThe main point is the adding support of \u003cb\u003estored objects\u003c/b\u003e. This can be seen as immutable variables initialized at compile time and stored in flash.\nLot of bug fixes and improvements have been added.  \nTwo examples Thermometre (MSP430G2231) and nRF24l01+ relay (MSP430G2553) have been added.  \n  \nDetails:\n\n* Cleaning of the code\n* Minor bugs fixed\n* Adding stored objects\n* Adding the standard function \u003cB\u003ePTR\u003c/B\u003e (see below)\n\n## Language differences from Oberon 07 for Cortex M4\n### Stored objects\nThe Oberon 07 language has no support for defining constants objects like records.\n In microcontroller field, is is very useful to have compile time initialized objects stored in embedded flash memory.  \n OMSP provides a way to achieve this, a concept similar as the \"one time initialization\" concept implemented in OM4 compiler.\n  Let's see it trough a simplified example:\n  \n    MODULE nrf24pRelay;\n      CONST\n        EMIT* = {1..3};\n        LOW_POWER* = {1, 5};\n        EN_DPL* = {2}; EN_ACK_PAY* = {1} + EN_DPL;\n\n      TYPE\n        RadioPipe* = RECORD payload_length*: BYTE; address*: ARRAY 6 OF CHAR END;\n        RadioSetup* = RECORD direction*: BYTESET; channel*: BYTE; rf_setup*, features*: BYTESET;\n          pipes_count*: BYTE; pipes*: ARRAY 6 OF RadioPipe\n        END;\n      VAR confEmitter: RadioSetup-;\n    \n    BEGIN\n      confEmitter.direction := EMIT; confEmitter.channel := 110; confEmitter.rf_setup := LOW_POWER;\n      confEmitter.features := EN_ACK_PAY; confEmitter.pipes_count := 1;\n      confEmitter.pipes[0].payload_length := 0; confEmitter.pipes[0].address := \"RSCHO\";\n    END nrf24pRelay.\n\nNotice the hyphen character after `RadioSetup` type in the VAR clause.\nIt means that the variable `confEmitter` is immutable and will be stored in the embedded flash memory.\nThe actual definition of this object is computed at compiler or link time and outputted to the\n constant section of the object file.  \nBecause all the initialization is performed at compile/link time, no executable code is generated in the module's body.\n\n### New types\n#### Integer and Byte pointers\n**PINTEGER**, **PBYTE**, **PSET** and **PBYTESET** types have been defined to enforce the access size on\nspecific memory locations. See msp430g2553.Mod as an example.\n#### 8 bit sets\n**BYTESET** type has been added to handle byte access register of the MSP430 architecture.\n### In-line procedures and functions\nDue to the difference of instruction set architectures, the following\nIn-line procedures or functions have been removed: **LSL(x, n)**, \n**ASR(x, n)**, **ROR(x, n)**  \nWith PINTEGER and PBYTE types, **SYSTEM.PUT** and **SYSTEM.GET** \nare no more useful and are removed.  \nThis compiler is board agnostic, so **LED** is removed.\n#### New in-line functions\n**TOSET(x)** turns type of x into SET type.  \n#### New in-line procedures\n**BIC(x, y)** is an optimized equivalent of **x := x - y** with x and y of type set  \n**BIS(x, y)** is an optimized equivalent of **x := x + y** with x and y of type set  \n**XOR(x, y)** is an optimized equivalent of **x := x / y** with x and y of type set  \n**AND(x, y)** is an optimized equivalent of **x := x * y** with x and y of type set  \n**CLRC** generates a \"clear carry\" machine instruction  \n**NOP** generates a \"no operation\" machine instruction  \n**ADC(x, y)** is an optimized equivalent of **x := x + y + \u003ccarry\u003e** with x and y of numeric type  \n**SBC(x, y)** is an optimized equivalent of **x := x - y - 1 + \u003ccarry\u003e** with x and y of numeric type  \n**RLA(x, n)** is an optimized equivalent of **x := x * 2\u003csup\u003en\u003c/sup\u003e** with x and y of numeric type  \n**RLC(x)** performs a rotate left through carry on **x**  \n**RRA(x, n)** is an optimized equivalent of **x := x / 2\u003csup\u003en\u003c/sup\u003e** with x and y of numeric type  \n**RRC(x)** performs a rotate right through carry on **x**  \n**SWPB(x)** exchanges high and low bytes of **x**  \n**PTR(t, x)** is a type safe equivalent of **SYSTEM.VAL(t, SYSTEM.ADR(x))**. In addition, the compiler checks that\nthe type **t** is a pointer to the type of the expression **x**  \n#### In-line functions with different semantics\n**BIT(x, y)** is an optimized equivalent of the condition **\"x*y # {}\"**\n#### New SYSTEM in-line procedures\n**BIC_SR** allows to clear bits of the status register  \n**BIS_SR** allows to set bits of the status register  \n**BIC_SR_ON_EXIT** allows to clear bits of the status register at the exit of an interrupt handler  \n**BIS_SR_ON_EXIT** allows to set bits of the status register at the exit of an interrupt handler  \n## Specific extensions\n### Leaf procedures\nLeaf procedures allow parameters and local variables to be implemented in MSP430 registers.  \nThe user has the responsablility to choose which parameters or local variables will be stored in registers, \nby adding an asterisk after the type of the parameters or variables.  \nLeaf procedures cannot call other procedures.\n\nFor example, in the module **Arith** the function **mul16** uses register to store\nthe parameters **x** and **y** and the the local parameter **r**\n\n    PROCEDURE mul16*(x, y: INTEGER*): INTEGER;\n      VAR r: INTEGER*;\n    BEGIN r := 0; \n      WHILE x # 0 DO IF ODD(x) THEN INC(r, y) END; INC(y, y); CLRC; RRC(x) END\n      RETURN r\n    END mul16;\n  \n### Runtime modules\nDue to the limited RAM and Flash resources, it is useful to remove the trap\noverhead from the final code.  \nFor the MSP430 target, I implemented optional runtime modules, which are for now\nTraps and Arith. The Traps module implement the trap handlers code. For example,\nTraps.ArrayOutOfRange is called when an out of range index is detected at the\nexecution time.  \nIf an handler is not defined, the corresponding checking code is not generated, \neliminating the overhead related to the associated trap.\n### Vector list\nAn asterisk after a procedure name defines an interrupt handler. The asterisk\nmust be followed by one or more vector numbers separated by commas, indicating\nwhich interrupts the handler will be servicing.\n### Register protection\nAn interrupt handler must restore all register to their initial value before exiting.\nThe MSP430 compiler automatically build a list of altered register and triggers an error \nif they are not properly restored before the interrupt handler exit. To deal with this, \nthe user can declare a set of registers to be save, in any procedure or function declaration.\nThe compiler uses this to generate the appropriate set of **PUSH** and **POP** instructions,\nprotecting the specified registers from corruption.  \n  \nFor example, the following handler code pushes R4 on the stack at entry and pops the saved value of\nR4 from the stack on exit:  \n  \n\tPROCEDURE* (M.USCIAB0TX_VECTOR) {4} USCIAB0TX_ISR;\n\t  VAR rx_val: BYTE;\n\tBEGIN\n \t  .\n \t  .\n\tEND USCIAB0TX_ISR;\n\nAdditionally, the register set declaration can be used in the declaration of procedure or function types.\nIn that case, it plays the role of a contract between the procedure type and actual procedure assigned to a\nvariable of the procedure type. The compiler ensures that the actual procedure protects all the registers\nspecified in the procedure type declaration.\n\nFor example, the module **HALGUImsp430g255x** exports the Callback function type, requesting that any assigned function\nprotects the registers R4 to R15. Please note that as the Callback type denotes a non-leaf function, the register R15 is\nused to convey the return value and therefore is automatically excluded from the register protection set.\n\n\tMODULE HALGUImsp430g255x;\n\t  IMPORT SYSTEM, HALSYSmsp430g255x, HALIOmsp430g255x, M := msp430g2553;\n\t\n\t  TYPE Callback* = PROCEDURE {4..15} (data: CHAR): BOOLEAN;\n\t    .\n\t    .\n\tEND HALGUImsp430g255x.\n\n The actual procedure, defined in the module **GUIMpack**, complies wtih this requirement.\n\n\tMODULE GUIMpack;\n\t  IMPORT SYSTEM, MP := mpack, MC := MpackCallbacks, HG := HALGUImsp430g255x;\n\t    .\n\t    .\n\t  PROCEDURE {4..14} RxByteCallback(data: CHAR): BOOLEAN;\n\t    VAR ret: BOOLEAN;\n\t  BEGIN ret := FALSE;\n\t    IF ~rxInProgress THEN\n\t      IF data # 0AX THEN rxInProgress := TRUE; charCnt := 0; rxString[charCnt] := data END\n\t    ELSE (* in progress *)\n\t      INC(charCnt);\n\t      IF data # 0AX THEN\n\t        IF charCnt \u003e= MAX_STR_LEN THEN rxInProgress := FALSE ELSE rxString[charCnt] := data END\n\t      ELSE (* String receive complete *) rxInProgress := FALSE; rxString[charCnt] := 0X;\n\t        IF ParseString() THEN ret := TRUE; (* wake-up MCU *) END\n\t      END\n\t    END\n\t\n\t    RETURN ret\n\t  END RxByteCallback;\n\t    .\n\t    .\n\tEND GUIMpack.\n\n## Another example\nTo show what a real program looks like, this is an example based on \nmsp430g2xx3_lpm3_vlo.c, a C language example from TI.\n\n\t(******************************************************************************\n\t//  MSP430G2xx3 Demo - Basic Clock, LPM3 Using WDT ISR, VLO ACLK\n\t//\n\t//  Description: This program operates MSP430 normally in LPM3, pulsing P1.0\n\t//  ~ 6 second intervals. WDT ISR used to wake-up system. All I/O configured\n\t//  as low outputs to eliminate floating inputs. Current consumption does\n\t//  increase when LED is powered on P1.0. Demo for measuring LPM3 current.\n\t//  ACLK = VLO/2, MCLK = SMCLK = default DCO\n\t//\n\t//\n\t//           MSP430G2xx3\n\t//         ---------------\n\t//     /|\\|            XIN|-\n\t//      | |               |\n\t//      --|RST        XOUT|-\n\t//        |               |\n\t//        |           P1.0|--\u003eLED\n\t//\n\t//  Eason Zhou\n\t//  Texas Instruments Inc.\n\t//  January 2020\n\t//  Ported to Oberon by C. Schoffit 30.08.2024\n\t//******************************************************************************)\n\t\n\tMODULE msp430g2xx3lpm3vlo;\n\t  IMPORT SYSTEM, M := msp430g2553;\n\t\n\t  VAR i: INTEGER;\n\t\n\t  PROCEDURE* (M.WDT_VECTOR) watchdog_timer;\n\t  BEGIN SYSTEM.BIC_SR_ON_EXIT(M.LPM3_bits) (* Clear LPM3 bits from SR backup *)\n\t  END watchdog_timer;\n\t\n\tBEGIN\n\t  BIS(M.BCSCTL1^, M.DIVA_1); (* ACLK/2 *)\n\t  BIS(M.BCSCTL3^, M.LFXT1S_2); (* ACLK = VLO *)\n\t  M.WDTCTL^ := M.WDT_ADLY_1000; (* Interval timer *)\n\t  BIS(M.IE1^, M.WDTIE); (* Enable WDT interrupt *)\n\t  M.P1DIR^ := {0..7}; (* All P1.x outputs *)\n\t  M.P1OUT^ := {}; (* All P1.x reset *)\n\t  M.P2DIR^ := {0..7}; (* All P2.x outputs *)\n\t  M.P2OUT^ := {}; (* All P2.x reset *)\n\t  M.P3DIR^ := {0..7}; (* All P3.x outputs *)\n\t  M.P3OUT^ := {}; (* All P3.x reset *)\n\t  \n\t  REPEAT \n\t    BIS(M.P1OUT^, {0}); (* Set P1.0 LED on *)\n\t    i := 10000; REPEAT DEC(i) UNTIL i \u003c= 0; (* Delay *)\n\t    BIC(M.P1OUT^, {0}); (* Reset P1.0 LED off *)\n\t    SYSTEM.BIS_SR(M.LPM3_bits + M.GIE) (* Enter LPM3 *)\n\t  UNTIL FALSE\n\tEND msp430g2xx3lpm3vlo.\n\nCompilation and linking is done by OMSPP and OMSPL modules:  \n  \nOMSPP.Compile msp430g2553 msp430g2xx3lpm3vlo ~  \nOMSPL.Link 32 4000H 200H msp430g2xx3lpm3vlo ~  \n  \nThe linker produces a program in TI-TXT format:  \n  \n\t@C000  \n\tB1 C0 D0 00 00 00 00 13 F2 D0 10 00 57 00 F2 D0  \n\t20 00 53 00 B2 40 1C 5A 20 01 D2 D3 00 00 F2 43  \n\t22 00 C2 43 21 00 F2 43 2A 00 C2 43 29 00 F2 43  \n\t1A 00 C2 43 19 00 D2 D3 21 00 B2 40 10 27 00 02  \n\t92 83 00 02 0F 43 1F 92 00 02 FA 3B D2 C3 21 00  \n\t32 D0 D8 00 F0 3F 30 41 31 40 00 04 B0 12 08 C0  \n\t32 D0 10 00 FD 3F  \n\t@FFE0  \n\t60 C0 60 C0 60 C0 60 C0 60 C0 60 C0 60 C0 60 C0  \n\t60 C0 60 C0 00 C0 60 C0 60 C0 60 C0 60 C0 58 C0  \n\tq  \n\nThis program can be installed on a MSP430 device with the \nMSP Flasher tool provided by Texas Instruments.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fef15c%2Fomsp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fef15c%2Fomsp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fef15c%2Fomsp/lists"}