This might sound like a weird question...
Just a quick query really, since the new Due's Atmel Arm bases Cortex M3 uses Thumb2 as low level instruction set, how easy (or hard) is it to write stuff on that level in C++? (if needed, probably not)
Bypassing Wire of course.
I assume Thumb2 is the name of the processor's machine language (or assembly language) instruction set????
I've never tried it...
I think you have to check your compiler's documentation. Look for "assembly". "ASSEMBLER", or "ASM". I don't have my C/C++ references handy, and I don't remember if this is part of the ISO/ANSI language standard, or if it's optional. (If you program purely in assembly, then technically you use an assembler instead of a compiler.)
I found [u]this[/u] for the arduino/AVR processor.
I believe it gets rather tricky when you combine C/C++ with assembly because you have to save the state of the processor (internal registers, etc.) and restore them before returning to your C/C++ program. Maybe the compiler sometimes takes care of that, but I'm not sure.
The Due is using the CMSIS abstraction layer, this defines a heap of structures with elements that match the underlying hardware, so you can reference registers directly like this
NVIC->ISER = x;
to write x into the Nested Vector Interrupt Controller's ISER register. Same applies for the UARTs, timers and everything else. NVIC in this case is the address of the controller and ISER and element in the structure at the same offset as the ISER reg in the hardware.
Another example
LPC_UART0->THR = *BufferPtr;
This writes a character from a buffer into the Transmit Holding Reg of UART0. (NOTE: this is for an LPC, the names will change for SAM but the basic idea is the same).
So all the places we used to do
DDRB |= _BV(3);
Will now be something like
PIOB->PIO_SODR |= (1 << 3); // _BV may still work if the macro has been ported
But don't quote me on the names used, I'm not very familiar with the SAM register names yet.
I assume Thumb2 is the name of the processor's machine language (or assembly language) instruction set
Correct.
As for genuine assembly language, given the above and the great optimisation of modern compilers it's hard to imagine when it would be required, but the GCC compiler allows it in the same way we currently do inline assembler with the AVRs. eg
asm ("valid asm code here");
An alternative is to have a separate assembly file with just ASM code in that and link it into the project.
i meant Wiring, you'd use wiring first, then if that isn't the answer to ur dreams u do it in C/C++, then if that doesn't give u the power to do what you want then it's assembler (thumb2).
It was just a theoretical question really. I don't know much about it tbh, it just that we are starting to cover assembly language based on ARM7 in uni now.
I have checked this procedure for viewing the assembly of both Teensy3.0 and Arduino Due, it works on both the new platforms as well as the current AVR compiler and will give you an idea of what you are up against if you want to go that low -
And the question, does anyone have a link to a good document or book on the CMSIS ?
I know it's awful stuff, but it's nice to know the possibilities, who knows, I might get into it if I enjoy this microprocessor and digital module in yr 2 uni.
Thanks
then if that doesn't give u the power to do what you want then it's assembler (thumb2).
Thumb isn't about speed/power efficiency, it's about space efficiency, and I can't imagine why anyone would want to write any explicitly.
I work on systems running to many MLOCs of C and C++, and about the only time we ever see ARM assembler is for a very few critical memory fill or copy operations.
Disclaimer: I can (just about) read ARM assembler (very, very occasionally, I have to follow code down to debug it), but I've certainly never written any.
ARM is a RISC processor, and all native instructions are 32 bits wide.
Thumb is a special mode the processor has that allows it to execute a set of 16 bit instructions, allowing you, in theory, to get twice as many instructions into a given memory space. Obviously, there are compromises to be made, usually performance.
Thumb2 is a further extension, with the aim of reducing the space/performance trade-off.
Thumb/Thumb2 are a subset of the full ARM instruction set, the instructions fit into 16 bits and therefore are more efficient WRT flash usage.
CMSIS is really (AFAIK) just a lot of defines and structs that tend to provide an abstraction layer, but it's only one level about dicking around with raw addresses. So my example
LPC_UART0->THR
is really just a human-friendly version of the address 0x40008000, while the Transmit Holding Reg of UART1
LPC_UART1->THR
is at 0x4000C000
Here is an example of the USART0 part of a header file that implements the CMSIS stuff
typedef struct { /*!< (@ 0x40008000) UART0 Structure */
union {
__IO uint32_t DLL; /*!< (@ 0x40008000) Divisor Latch LSB. Least significant byte of the baud rate divisor value. The full divisor is used to generate a baud rate from the fractional rate divider. (DLAB = 1) */
__IO uint32_t THR; /*!< (@ 0x40008000) Transmit Holding Register. The next character to be transmitted is written here. (DLAB=0) */
__I uint32_t RBR; /*!< (@ 0x40008000) Receiver Buffer Register. Contains the next received character to be read. (DLAB=0) */
};
union {
__IO uint32_t IER; /*!< (@ 0x40008004) Interrupt Enable Register. Contains individual interrupt enable bits for the 7 potential UART interrupts. (DLAB=0) */
__IO uint32_t DLM; /*!< (@ 0x40008004) Divisor Latch MSB. Most significant byte of the baud rate divisor value. The full divisor is used to generate a baud rate from the fractional rate divider. (DLAB = 1) */
};
union {
__IO uint32_t FCR; /*!< (@ 0x40008008) FIFO Control Register. Controls UART FIFO usage and modes. */
__I uint32_t IIR; /*!< (@ 0x40008008) Interrupt ID Register. Identifies which interrupt(s) are pending. */
};
__IO uint32_t LCR; /*!< (@ 0x4000800C) Line Control Register. Contains controls for frame formatting and break generation. */
__IO uint32_t MCR; /*!< (@ 0x40008010) Modem control register */
__I uint32_t LSR; /*!< (@ 0x40008014) Line Status Register. Contains flags for transmit and receive status, including line errors. */
__I uint32_t MSR; /*!< (@ 0x40008018) Modem status register */
__IO uint32_t SCR; /*!< (@ 0x4000801C) Scratch Pad Register. Eight-bit temporary storage for software. */
__IO uint32_t ACR; /*!< (@ 0x40008020) Auto-baud Control Register. Contains controls for the auto-baud feature. */
__I uint32_t RESERVED0[1];
__IO uint32_t FDR; /*!< (@ 0x40008028) Fractional Divider Register. Generates a clock input for the baud rate divider. */
__I uint32_t RESERVED1[1];
__IO uint32_t TER; /*!< (@ 0x40008030) Transmit Enable Register. Turns off UART transmitter for use with software flow control. */
__I uint32_t RESERVED2[6];
__IO uint32_t RS485CTRL; /*!< (@ 0x4000804C) RS-485/EIA-485 Control. Contains controls to configure various aspects of RS-485/EIA-485 modes. */
__IO uint32_t RS485ADRMATCH; /*!< (@ 0x40008050) RS-485/EIA-485 address match. Contains the address match value for RS-485/EIA-485 mode. */
__IO uint32_t RS485DLY; /*!< (@ 0x40008054) RS-485/EIA-485 direction control delay. */
__I uint32_t FIFOLVL; /*!< (@ 0x40008058) FIFO Level register. Provides the current fill levels of the transmit and receive FIFOs. */
} LPC_UART0_Type;
The SAM will have similar but I'm having a hard time finding it in the 1.5 install.
Holds a stack of .H files (one for each peripheral) with all the defines for the register addresses.
So at first glance it seems that the way the SAM is done is different to the LPC implementation.
LPC_UART0->THR
on an LPC would be
REG_USART0_THR
on the Due. Kind of makes you wonder what the point of CMSIS is, not much of an abstraction layer for the peripherals but maybe OK for the ARM core itself.
Where are all the beta testers, they should be experts by now and be able to describe this.