4MHz PWM with 50% duty cycle on Arduino 101

Hi All,
I need help to generate 4MHz PWM 50% duty cycle on Arduino 101.
We need to use it for Smartcard communication.

Many Thanks!

I would love to know how to do this as well. Currently Tone and Curietimer1 is software based, and can only handle up to 100kHz utilizing software, and timer 1 on the ARC core, timer0 is already heavily used, and should not be touched.

There are 4 timers on the quark side of the board, and utilizing registers I can get the timer to count 4MHz with a 50% duty cycle, but I am stuck on getting the timer to output a PWM on any of the pins. Quark Timer1 should be connected to digital pin ~3, and is PWM(0) according to:


page 423 - 426

The following code will get your timer working:

#include "portable.h"
#include "scss_registers.h"

// Register Adresses
#define timerBase 0xB0000800
#define Timer1EOI 0x0C
#define Timer1ControlReg 0x08
#define Timer1CurrentValue 0x04
#define Timer1LoadCount2 0XB4

uint32_t timer1ctrl = timerBase + Timer1ControlReg;
uint32_t timer1cv = timerBase + Timer1CurrentValue;
uint32_t timer1rst = timerBase + Timer1EOI;
uint32_t timer1LC2 = timerBase + Timer1LoadCount2;

bool endLoop = true;
uint32_t hold;

void setup() {
// put your setup code here, to run once:
MMIO_REG_VAL(timerBase) = 0x04; // Hex number for High Cycle Clock Ticks of 32MHz (4 for 4MHz 50%)
MMIO_REG_VAL(timer1LC2) = 0x08; // Hex number for Low cycle Clock Ticks of 32MHz (8 for 4MHz)
MMIO_REG_VAL(timer1ctrl) = 0x0B; // Configures settings from page 428 Launch the timer in the correct mode

// Hold is used to check multiple register values to ensure the correct values are in them
//hold = timerBase;
pinMode(3, OUTPUT);

void loop() {
// put your main code here, to run repeatedly:

// This shows that the timer is running much faster than the software loop can keep up with, so I assume it is working,
// But it will not output on pin ~3
Serial.print("timer : ");
Serial.println(MMIO_REG_VAL(timer1cv), HEX); /* Value will start from 0 and count to Low value and then repeat*/

// hold = hold + 0x04;
//Serial.println(hold, HEX);
//Serial.println(MMIO_REG_VAL(hold), HEX); /* MUST BE 1000_0242h */

// ****************** END Code **********************

I believe the only thing that still needs to be configured is to get GPIO_SS[10] to PWM[0] from default function_0 to function_1 (page 42). If you figure out how to do this I believe it should all work, but I am at a loss for how to accomplish that.

Here is the source code for the arduino 101, not sure if the GPIO function can be configured through it though, because it says it is configured with the firmware

Please let me know if you figure out this last part, or find some other way to accomplish generating a 4MHz pwm.

So the developers were kind enough to point me to their code for changing the GPIO function. It is line 97 to 102 in:

So tried adding:

int pin = 3;
int PWM_MUX_MODE = 1;


to my above code to no avail. in their code they use p->ulSocPin instead of pin, but I have not found the ulSocPin reference that they are pointing to. I think I might need a pin register address and not the actual number. I dunno, let me know if you get this figured out.

Also line 139 of the above reference looks like a perfect function for what you are looking for, but again I can't get that to work either.

Best of luck to you

Bang, it works now. I think there might be something about one extra 32MHz tick on the low side, but I hope this is good enough for you.

// ***********************************************************************

#include "portable.h"
#include "scss_registers.h"
#include "wiring_analog.h"
#include "variant.h"

void setup() {

uint8_t pinmuxMode[NUM_DIGITAL_PINS];
uint32_t offset;
uint32_t hcnt = 0x4; // Hex number for High Cycle Clock Ticks of 32MHz (4 for 4MHz 50%)
uint32_t lcnt = 0x4; // Hex number for Low cycle Clock Ticks of 32MHz (4 for 4MHz)
uint8_t pin = 3;
PinDescription *p = &g_APinDescription[pin];

/* Set the high count period (duty cycle) */
offset = ((p->ulPwmChan * QRK_PWM_N_LCNT2_LEN) + QRK_PWM_N_LOAD_COUNT2);
MMIO_REG_VAL(QRK_PWM_BASE_ADDR + offset) = hcnt;

/* Set the low count period (duty cycle) */
offset = ((p->ulPwmChan * QRK_PWM_N_REGS_LEN) + QRK_PWM_N_LOAD_COUNT1);
MMIO_REG_VAL(QRK_PWM_BASE_ADDR + offset) = lcnt;

/* start the PWM output */
offset = ((p->ulPwmChan * QRK_PWM_N_REGS_LEN) + QRK_PWM_N_CONTROL);

if(pinmuxMode[pin] != PWM_MUX_MODE)
/* Disable pull-up and set pin mux for PWM output */
SET_PIN_PULLUP(p->ulSocPin, 0);

void loop() {
// put your main code here, to run repeatedly: