I want to make PiFm https://github.com/rm-hull/pifm/blob/master/pifm.cpp compatible on OrangePi One ( h3 AllWinner ARM processor )
I guess, to do compatible i just? set the good register addresses no ?
On PiFm i found those address :
#define CM_GP0CTL (0x7e101070)
#define GPFSEL0 (0x7E200000)
#define CM_GP0DIV (0x7e101074)
#define CLKBASE (0x7E101000)
#define DMABASE (0x7E007000)
#define PWMBASE (0x7e20C000) /* PWM controller */
But on the H3 datasheet http://dl.linux-sunxi.org/H3/Allwinner_H3_Datasheet_V1.0.pdf i can't translate these addresses.
I'm not a expert on ARM/Programmation but PiFm will work on OrangePi One ?
(Sorry for my english, i'm french)
Thanks by advance
Regards
Converting this program to run on the Allwinner SoC would involve rewriting it entirely, if it's even possible.
PiFm depends on being able to turn the Broadcom SoC's PWM peripheral on and off through crafted DMA requests. This is not an option on the Allwinner; the PWM peripheral does not have a DMA port (datasheet page 193).
Related
I've been trying to port some of my AVR code to drive a simple SPI LCD to ARM as a learning exercise (I'm very new to ARM in general). For this I just need to use SPI in master mode.
I looked in the datasheet for my device (STM32F103C8) and found that the SPI1 pins I need, SCK and MOSI are mapped as alternative functions of PA5 and PA7, respectively, along with other peripherals (pg.29). My understanding is that in order to use the SPI function on these pins, I need to make sure that anything else mapped to the same pin is disabled. When looking at the defaults for the peripheral clock control register, however, it looks like the other features are already disabled.
I looked at the SPI section in the reference manual, including section 25.3.3 - Configuring the SPI in master mode. First I enabled the SPI1 master clock in APB2ENR and followed the steps in this section to configure SPI1 to my needs. I also changed the settings for PA5/7 to set their mode to "Alternate Function Output push-pull" (9.1.4). Finally, I enabled SPI1 by setting CR1_SPE.
From my reading, I had thought that by loading a value into the SPI1 data register after configuring SPI as above, the data would be shifted out. However, after writing the data, the TXE flag in the SPI status register never becomes set, indicating that the data I wrote into it is just sat there.
At this point, I'm assuming that there is something else I've failed to configure correctly. For example, I'm not 100% sure about what to do with the PA5/7 pins. I've tried to understand what I can from the datasheets, but I'm not getting anywhere. Is there anything else that needs to be done before it'll work?
I'm almost certain that you did not set SSM and SSI bits in SPIx->CR1 register. SPI in these chips is pretty simple, for the polled transfers you need to set SSM, SSI, SPE, MSTR, correct format (LSBFIRST, CPOL, CPHA) and proper baudrate (BR) in SPIx->CR1 and you're good to go.
I have microprocessor at32uc3b0256 and I want turn on leds, (simple program from examples). To do this I use Atmel Studio. I found sample code:
#ifndef F_CPU
#define F_CPU 16000000UL // 16 MHz clock speed
#endif
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRC = 0xFF; //Makes PORTC as Output
while(1) //infinite loop
{
PORTC = 0xFF; //Turns ON All LEDs
_delay_ms(1000); //1 second delay
PORTC= 0x00; //Turns OFF All LEDs
_delay_ms(1000); //1 second delay
}
}
But when i wrote it to Atmel Studio i got some errors, Atmel Studio dont see DDRC and PORTs as variable. How can I fix it?
Screen form Atmel Studio
You are using GPIO example for AVR8 architecture. AVR32 architecture is completely different introducing GPIO module as separate HW block connected through PBA (I think). There are no registers like DDRC,...
You can look at AVR32 architecture as on network of subcomponents where MCU core is only one of the modules. There are 2 main buses PBA and PBB each connected to different modules.
To make AVR32 firmware work you need do this:
configure and start main MCU core clock you want to use
AVR32 MCU core is usually running at low 32KHz clock after reset. To achieve better performance you need higher clock up to 66MHz. I usually start PLL at some common frequency and divide all clocks (CPU,PBA,PBB,HSB) from it later. As a source for the PLL you need some clock for example internal RC or oscillator driven by external crystal. If you want also USB then you need to take in mind it needs specific frequency so compromise ... For more info check SCIF module in datasheet and or in examples.
switch to it when started properly
Either wait a bit (100ms) or check if clock is running directly (SCIF module has some capabilities for it I think).
configure/start used HW modules
now do your stuff
Bootlaoder
Another thing you need to take care of is the boot loader. I do not like JTAG as I have a bad experience with it (does not take much to fry it and the programing with it is really uncomfortable). With JTAG you can easily wipe out bootloader (each chip is shipped with it) and trust me getting it back to work is really nasty.
Bootloader on the other hand is simple and elegant. For example I use FLIP and has simple comandline file for programing chip. Then I just open command prompt execute it. And on each rebuild/programming I just hit up arrow to repeat last command in the prompt and hit enter. In comparison to many clicks with JTAG is this much faster and simpler. Here example of the cmd:
avr32-objcopy -O ihex AT32UC3L064.elf AT32UC3L064.hex
Batchisp -device AT32UC3L064 -hardware RS232 -port COM1 -baudrate 115200 -operation onfail abort memory flash erase f blankcheck loadbuffer AT32UC3L064.hex program start reset 0
The avr32-objcopy.exe is in the AVR studio bin directory.
With Bootloader you need to tell the compiler your program is not starting at 0x0000 because that would be overlapping with bootloader. To do that see the trampoline examples.
This is how my AVR32 app usually looks like:
#include <avr32/io.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "intc.c"
#include "gpio.c"
#include "pm_uc3l.c"
#include "scif_uc3l.c"
#include "adcifb.c"
#include "flashcdw.c"
#include "pdca.c"
//#include "pwma.c"
#include "tc.c"
#include "usart.c"
#include "eic.c"
#include "genclk.h"
#include "osc.c"
#include "dfll.c"
#include "sysclk.c"
#include "status_codes.h"
#include "cycle_counter.h"
#include "sleep.h"
#include "delay.c"
#define cpu_clk 30000000
#define _LED AVR32_PIN_PA04
void system_init()
{
delay_init(115000);
Disable_global_interrupt();
INTC_init_interrupts();
scif_start_rc120M();
delay_ms(100);
pm_set_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_CPU,PM_CKSEL_DIVRATIO_4);
pm_set_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_PBA,PM_CKSEL_DIVRATIO_4);
pm_set_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_PBB,PM_CKSEL_DIVRATIO_4);
pm_set_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_HSB,PM_CKSEL_DIVRATIO_4);
pm_set_all_cksel(SCIF_RC120M_FREQ_HZ,cpu_clk,cpu_clk,cpu_clk);
flashcdw_set_flash_waitstate_and_readmode(cpu_clk);
pm_set_mclk_source(PM_CLK_SRC_RC120M);
delay_init(cpu_clk);
}
//------------------------------------------------------------------------------------------------
void wait_ms(U32 dt)
{
U32 t0,t1;
t0=Get_system_register(AVR32_COUNT);
dt=((dt*cpu_clk)+999)/1000;
t0&=RDTSC_mask;
for (;;)
{
t1=Get_system_register(AVR32_COUNT);
t1&=RDTSC_mask;
if (t0>t1) t1+=RDTSC_mask+1;
if ((t1-t0)>=dt) break;
}
}
//------------------------------------------------------------------------------------------------
void wait_us(U32 dt)
{
U32 t0,t1;
t0=Get_system_register(AVR32_COUNT);
dt=((dt*cpu_clk)+999999)/1000000;
t0&=RDTSC_mask;
for (;;)
{
t1=Get_system_register(AVR32_COUNT);
t1&=RDTSC_mask;
if (t0>t1) t1+=RDTSC_mask+1;
if ((t1-t0)>=dt) break;
}
}
//------------------------------------------------------------------------------------------------
int main(void)
{
system_init();
// here init what you need
gpio_configure_pin(_LED,GPIO_DIR_OUTPUT|GPIO_INIT_HIGH);
for (;;)
{
// here do your stuff
gpio_tgl_gpio_pin(_LED);
wait_ms(200);
}
//------------------------------------------------------------------------------------------------
I do not use framework manager instead I include the stuff myself... and my framework is rewritten to avoid unnecessary includes and slowdowns of compilation. Also beware that framework updates are not always compatible so sometimes after update your code will not compile ... It is better to have one solid framework and not update it unless you really need to.
Select only the modules you need to (no need to include them all). For example you need intc,gpio,scif etc my includes are from bigger project so many of them are useless for you and also not all headers/modules are available for all of the AVR32 chips.
I got a bit off topic (I think was necessary) so back to GPIO
The API and architecture is completely changed. Do not be fooled by the pin names. For example pin PA35 does not mean port A pin 35 !!! There is no port PA It is just naming convention without any real meaning to the architecture which is a bit silly and took me a while to got along with it. There are as many ports as needed to cover all the pins. Each port support 32 pins and the pin number is the real thing you need to know.
Each pin is defined somewhere in avr32/io.h as a define like AVR32_PIN_PA04 and it contains numerical value of the pin position in chips GPIO. To obtain gpio port/mask you just do this:
port = pin>>5
mask = 1<<(pin&31)
Now to access GPIO registers directly I recommend to look at gpio.c. You can set,res,test,read 32 pins at a time to speed up (if they are at the same port). The speed is dependent mainly on the buss clock (usually PBA for GPIO) so if your clock for it is low do not expect high toggle rate. beware GPIO access is slow and if not used wisely can kill the performance of your code...
If HW pins selected for your App are done wisely you can have really fast speeds. For example I got toggle speeds around 2-5 MHz !!!
Here example of setting a pin from gpio.c
void gpio_set_gpio_pin(uint32_t pin)
{
U32 bit= 1 << (pin & 0x1F);
volatile avr32_gpio_port_t *gpio_port = &GPIO.port[pin >> 5];
gpio_port->ovrs = bit; // Value to be driven on the I/O line: 1.
gpio_port->oders = bit; // The GPIO output driver is enabled for that pin.
gpio_port->gpers = bit; // The GPIO module controls that pin.
}
You can use this to set multiple pins at the same port simply by exchanging bit with the mask of all pins you want to set ...
If you are using Interrupts for GPIO beware that the interrupt controller INTC is also a separate module connected by buss and wrongly set clock or wait states can cause huge problems.
I already interfacing the GPS s-1216 module with 8051. Now I'm going to interfacing the same module with MSP430fr5969 launchpad. I facing the problem in starting itself that to which pin is connection will be doing? can anyone will solve this.. If it possible explain using code functions..
You can use any of this. Either 0 or 1.
PIN 20-TX1, PIN 21-RX1; PIN 24-TX0, PIN 25-RX0.
Select the appropriate function using selection register as each pin has more than 2 functions. In 8051 there is nothing called selection register. But here it is used to define the function of PIN.
Rest of the things are same as in 8051, like UART configuration, baud rate and TX RX functions.
Before trying UART, try blinky IO program to get the basic knowledge on MSP430
everybody,
i'm working with a high speed RS422 pci board (OXPCIe958) under Ubuntu.
The device can work up to 15Mbps. I need to work at 10Mbps, but i notice that under Linux,
if we use termois, the maximum speed that can be specified is B4000000 (4 Mbps).
Is there any way to specify custom baund rate in linux?? I tried to change the values
in termois.h:
#define B1152000 0010011
#define B1500000 0010012
#define B2000000 0010013
#define B2500000 0010014
#define B3000000 0010015
#define B3500000 0010016
#define B4000000 0010017 --> by default this is the last value
#define B4500000 0010018 --> Added
#define B5000000 0010020 --> Added
//#define __MAX_BAUD B4000000 --> Default value
#define __MAX_BAUD B10000000
But changes doesn't work. I cannot understand the meaning of the value assigned to BXXXXXX!!
The device works natively on linux and no driver must be specified. Looking into the device's datasheet, i saw that to specify the target baund rate, we must set some registers that change the prescaler, the latch divisor and the sample clock.
According to the data sheet, tha baund rate is given by:
Baundrate = inputclok/(sampleClock*divisor*prescaler)
Is there a way to set this registers under linux? the driver are in 8250.c and 8250_pci.c
Thanks in advance
This page has a Linux kernel patch that adds direct exposure of the registers, so that ioctl() can be used to program custom baud rates. It's pretty old though, but might be useful for you.
I knew there is a similar post:
Steps to make a LED blink from a C/C++ program?
But now I am working on a arm-based development board, and it seems to have two serial ports that I could use it to make a LED on or off.
Basically I think the flow is , make one pin in serial "1" or on and the LED will be turned on and "0" to make it off.
Is there some reference code in C-language I could refers?
Generally speaking, the board should come with some Board Support Package (BSP) which lets you control the built in I/O. Look for a serial library if you really want to use the Hardware flow control signals.
I'd recommend looking for some GPIO (General Purpose I/O, or digial I/O) on the board, which typically lets you configure it as an input or an output. You should be able to connect the LED via a current limiting resister between a digital I/O line and a ground pin. Make sure you have the LED oriented correctly if you connect it backwards it will block the current instead lighting. And as always make sure you check it out with a digital voltage meter before connecting it.
Even if you don't have a BSP for digital I/O the configuration is usually pretty simple.
Set a bit in a register to enable it, set bit in another register to select input or output they will normally be arranged in 8-bit "ports." Some systems allow you configure individual I/O pins, other will only allow you to configure the whole port for input or output. Then you just write a 1 or 0 to the bit you want to control in an write/output register.
ARM chips typically have a considerable amount of built in peripherals today, so most boards will just be bringing the I/O out to physical connectors on the board and you may need to read the chip vender's documentation to find the register memory map. Better board venders will supply documentation, a library (BSP) and examples. Luminary Micro even supplies chips with built in ethernet MACs and PHYs, just add a connector and Magnetics and you have a 1 chip Webserver.
This will, I'm afraid, be heavily dependent on the specifications of the particular arm-based development board you are using.
You need to find documentation specific to that board.
I used to do this kind of programming before.
You need to study the serial port connection
http://www.lammertbies.nl/comm/cable/RS-232.html
http://www.beyondlogic.org/serial/serial.htm
It has +5v, -5v on the output, I can't remember clearly now. Not every pin is needed.
I never use ARM before, but I use a 8-bit PIC controller to program it. I guess you can find a lot of example online.
The preferred alternative for controlling a GPIO is via a BSP. Because this BSP (board support package) does all the work for you in setting all peripherals to good defaults and and allowing you to call a function. Possibly your BSP of choice will have a function to write a byte to an 8-bit GPIO port; your LED will only have one bit. In this case your C code could look like: (at least: it will work like this on Luminary Micro kits). (Example code; requires a bit of extra work to make it compile especially on your kit).
/* each LED is addressed by an address (byte) and a bit-within-this-byte */
struct {
address, // address of IO register for LED port
bit // bit of LED
} LEDConfigPair;
struct LEDConfigPair LEDConfig[NUMBER_OF_LEDS] = {
{GPIO_PORTB_BASE,0}, // LED_0 is at port B0
{GPIO_PORTB_BASE,1} // LED_1 is at port B1
} ;
/* function LED_init configures the GPIOs where LEDs are connected as output */
led_init(void)
{
U32 i;
for(i=0;i<NUMBER_OF_LEDS;i++)
{
GPIODirModeSet( LEDConfig[i][0], LEDConfig[i][1], GPIO_DIR_MODE_OUT );
}
}
/* my LED function
set_led_state makes use of the BSP of Luminary Micro to access a GPIO function
Implementation: this BSP requires setting 8 port wide IO, so the function will calculate a mask (
*/
set_led_state(U8 led,bool state)
{
U8 andmask;
U8 setmask;
andmask = ~(1 << LEDConfig[led].bit);// a bitmask with all 1's except bit of LED
if (true == state)
{
setmask = (1 << LEDConfig[led].bit); // set bit for LED
} else
{
setmask = 0;
}
GPIOPinWrite(LEDConfig[led].address, andmask, setmask);
}
Of course this is all spelled out; it can be done in a single lines like this:
#DEFINE SETLEDSTATE(led,state) GPIOPinWrite(LEDConfig[led].address, ~(1<<LEDConfig[led].bit),(state<<LEDConfig[led].bit))
this will do the same, but only makes sense when you can dream bit masks, and you only want to toggle some LEDs to debug the real program...
The alternative: bare metal.
In this case you need to set up everything for yourself. For an embedded system, you need to be aware of pin multiplexing and power management (assuming memory controller and cpu clocks are already set up!)
initialization: set pin multiplexing in such a way that the function you want to control is actually mapped on the package.
initialization of pheripheral (in this case either a UART, or a GPIO function on the same pin)
You can't do it using Rx or Tx pins of Serial port. For that you just need to control the RTS or CTS pins of serial port.
Just google for "access COM port in VC++ code" and then control the RTS and CTS status pins to turn ON and OFF any external device.