Many people in this thread indicated a preference for a more Object Pascal interface to the registers and bits
I would like to retain the old school byte variable approach so that existing code works as far as possible - AVR isn't really supported in the current release so is backwards compatibility much of an issue?
I am in favour of dropping bit index constants (ADEN = 7) and change to bitmapped constants (ADEN = 128) to eliminate the whole register := (1 shl ADEN) construct
I could add all variations in principle, but it would clutter the source file (minor issue I think) and then there is the issue of naming the different types (ADCSRA, ADCSRAset, ADCSRAbitfield etc.) - so which type should have the bare register name ADCSRA? Probably the byte type variable?.
I think type helpers could eliminate some of the problems with naming different types that point to the same register address since the base type can be type casted in the type helper to various approaches. Not sure about this though.Perhaps move extended types to a different file - problem is then maintenance of separate files with similar functionality.
I have just seen question about usage of volatile in another thread: https://forum.lazarus.freepascal.org/index.php/topic,38961.msg266000.html.
Quote from: avra on November 15, 2017, 03:37:05 pmI have just seen question about usage of volatile in another thread: https://forum.lazarus.freepascal.org/index.php/topic,38961.msg266000.html. But please....Note volatile in Pascal is just a writable typed const instead of var... Has been since TP days....
So this is my first try at the fancy code generator:Code: Pascal [Select]... PORTB: byte absolute $25; // Port B Data Register PORTBset: TPORTBset absolute $25; PORTBrec: TPORTBrec absolute $25;...
Code: Pascal [Select]... TTIFR1rec = bitpacked record TOV1, OCF1A, OCF1B, reserved0, reserved1, ICF1, reserved2, reserved3: TBitField; end;...
- I don't like the bitnumbers getting potentially very general register looking names this way. Some pre or suffix would be ok, avoid clashes and be more distinct.
- I still would like to at least have an option to also generate the masks.
I will add this as an extra set of constants with say a prefix of mXXX or perhaps mskXXX.
I don't like the s-prefix for the set element names, should I change this to e for element or maybe se for set element
A preview of the auto generated AVR controller files have been prepared.
Note that there were some name clashes of different identifiers, hence I used s_ and m_ as prefixes for set element and bitmask names respectively.
QuoteNote that there were some name clashes of different identifiers, hence I used s_ and m_ as prefixes for set element and bitmask names respectively.I still don't like e_ and m_ prefixes with underscores but I can live with them since it is pretty much subjective.
Code: Pascal [Select]uart_init1(...);fpc_shr_qword(...);fpc_div_mod_word(...);spi_transfer(...);Huh, so many underscores and low cases feel like using some C lib. Is it possible to make it more like we are used with FPC/LAZ/DELPHI, please?I would also prefer single overloaded DivMod() which accepts different types instead of each being a completely separate (if they are intended for the user, after all):Code: Pascal [Select]procedure fpc_div_mod_byte(Dividend, Divisor: byte; out result, remainder: byte);procedure fpc_div_mod_word(Dividend, Divisor: word; var result, remainder: word);procedure fpc_div_mod_dword(Dividend, Divisor: dword; var result, remainder: dword);function fpc_div_mod_qword(Dividend, Divisor: qword; out Remainder: qword): qword;
I didn't find type helpers for byte/word/dword/qword. Something like we have discussed previously. Do you have plans to add them as standard at all?
Since it is a 8-bit embedded world, assembly optimization will be needed in some of the libraries. It would be nice to decide what registers will never be used by the system and the system libraries, what registers would be used for function results, how to name register pairs, etc. I would suggest to make it compatible with AvrCo
I am not quite sure how good would FPC optional register optimization work for AVR, and if we can force specific variables to be stored in registers (if enough free registers are available). Have you looked into this topic yet?
Pointers to internal and external ram, flash and eeprom would need to be treated somehow different. There are also AVRs with flash bigger then 64KB. Have you thought about such things yet?
How did you manage to do this in examples:Code: Pascal [Select] pinport: byte absolute PORTB;It compiles on my standard FPC compiler only if I type adress $24 instead of PORTB. However I managed to overcome this issue on my side by defining const PORTBaddr = $24 in generated avr cpu unit and then using PORTBaddr instead of PORTB in both avr cpu unit and example code.
I see that all examples follow flat workflow - pretty much GCC and Arduino way. While that is not bad at all, I am very spoiled by AvrCo way of doing things so let me give you a quick insight that might be used as a potential inspiration. AvrCo allows flat program workflow extended with interrupts when needed, but it also provides SysTick, Tasks and Processes. SysTick is a simple system interrupt (10ms by default but can be any period) extended with an optional user callback and used for system and drivers. No more constant polling for ADC readings, no more manual debouncing of inputs, manual matrix keyboard scanning, manual key autorepeat, we have various funtion timeouts, automatic 7seg and 14seg display refresh, automatic PWM or DAC output change, automatic soft and hard RTC handling with user callbacks, automatic handling of data collected from interrupt based drivers like pulse/freq counters or encoders, automatic step motor ramps, etc. Most drivers exploit SysTick so user code looks clean and without GCC like bloat we are used to. Drivers also have callbacks, and IO callbacks are specially usefull. For example, all character or graphical LCD functions are universal. There is example code for 8-9 display models, but if you want to use a not supported one, you just implement IO callbacks for your device, and positioning, drawing, text output and other functions immediatelly work out of the box. The same is for RTC and many other drivers. You can access serial and other types of communication directly like in GCC, but you can also use a interrupt based driver that stores characters into a buffer that you just need to poll to sea if there is anything to read. You might even sleep a process until data is available, since pipes and semaphores are implemented. There is also a round robin scheduler with cyclic tasks and processes with priorities. Tasks have a predefined maximum time for running, and they are killed if that max time is somehow reached. Processes are just temporary interrupted and they simply continue where they left on next schedule. This powerfull multitasking concept allows for example one or more communication processes, an IO task, main logic process, etc. Each as a separate identity easy to follow and develop. Only C based RTOS can match this.
Whatever path you decide to go, I really think that you have already done a very nice job. Thumbs up!
Quote from: avra on December 13, 2017, 11:11:29 amQuoteNote that there were some name clashes of different identifiers, hence I used s_ and m_ as prefixes for set element and bitmask names respectively.I still don't like e_ and m_ prefixes with underscores but I can live with them since it is pretty much subjective. Any alternative suggestions? I would like to adopt a naming convention that clearly relate to the standard bit name, but also indicate how the alternative identifier differs (bitmask, set element).
QuoteI didn't find type helpers for byte/word/dword/qword. Something like we have discussed previously. Do you have plans to add them as standard at all?My thought was that these will be generic helpers, so will sit in a separate unit.
QuoteSince it is a 8-bit embedded world, assembly optimization will be needed in some of the libraries. It would be nice to decide what registers will never be used by the system and the system libraries, what registers would be used for function results, how to name register pairs, etc. I would suggest to make it compatible with AvrCo The compiler follows the avr-libc convention. Register naming follows Atmel's nomenclature (r0 - r31 and X, Y, Z for the upper 6 register pairs).
QuoteI am not quite sure how good would FPC optional register optimization work for AVR, and if we can force specific variables to be stored in registers (if enough free registers are available). Have you looked into this topic yet?A related discussion. I don't think binding a specific variable to a register is possible, but I don't know for sure.
QuotePointers to internal and external ram, flash and eeprom would need to be treated somehow different. There are also AVRs with flash bigger then 64KB. Have you thought about such things yet?This is being debated. It is currently possible to put data into flash or eeprom with the section modifier, but accessing the data requires some assembler at the moment.