Skip to content
Snippets Groups Projects
Commit ed37f661 authored by Sam Calisch's avatar Sam Calisch
Browse files

add atsamd51

parent 5dc47c4e
No related branches found
No related tags found
No related merge requests found
Pipeline #2677 passed
<html>
<head>
<style>
pre code {
background-color: #eee;
border: 1px solid #999;
display: block;
padding: 20px;
}
</style>
</head>
<body>
<h1>ATSAMD51</h1>
<figure>
<img src='ring.jpg' height=50%>
<figcaption>Ring oscillator with ATSAMD51J19</figcaption>
</figure>
<p>This ring oscillator runs on the ATSAMD51J19 MCU using the Adafruit Feather dev board. The ATSAMD51J19 has an ARM Cortex-M4 running with a max speed of 120 MHz. Code for the oscillator is available <a href='ring.ino'>here</a>, or visible below.</p>
<pre>
<code>
#define portin PORT->Group[PORTA].IN.reg
#define outclr PORT->Group[PORTA].OUTCLR.reg
#define outset PORT->Group[PORTA].OUTSET.reg
#define out PORT->Group[PORTA].OUT.reg
#define outtgl PORT->Group[PORTA].OUTTGL.reg
const uint8_t in_pin = 21;
const uint32_t in_mask = 1ul&lt&ltin_pin;
const uint8_t out_pin = 22;
const uint32_t out_mask = 1ul&lt&ltout_pin;
void setup() {
// Set pin mode according to chapter '32.6.3 I/O Pin Configuration'
// enable input, to support reading back values, with pullups disabled
PORT->Group[PORTA].PINCFG[out_pin].reg = (uint8_t)(PORT_PINCFG_INEN) ;
// Set pin to output mode
PORT->Group[PORTA].DIRSET.reg = out_mask;
// Set in pin to input mode
PORT->Group[PORTA].PINCFG[in_pin].reg=(uint8_t)(PORT_PINCFG_INEN) ;
PORT->Group[PORTA].DIRCLR.reg = in_pin ;
//make sure port synchronizer always active, else we'll use extra clock cycles.
//I'm not sure I'm activating the synchronizer correctly, because I don't see a change when I add this...
PORT->Group[PORTA].CTRL.reg = in_mask;
//loop
while(1){
//ternary operator: assymetric 300ns (200-100)
//portin & in_mask ? outclr = out_mask : outset = out_mask;
//portin & in_mask ? outclr = out_mask : out = out_mask;
//full port inversion: symmetric 300ns
out = ~(portin);
//bitwise xor: 300ns
//out = ((portin ^ in_mask) << 1);
//if else, 300ns
/*if (portin & in_mask){
outclr = out_mask;
} else {
outset = out_mask;
}*/
}
}
void loop() {}
</code>
</pre>
<p>By default the port consumes extra clock cycles to save power and only sample the input pin when a read is requested (see description below). We can set the input synchronizer to always be active to avoid this delay. I've tried to do this above, but I need to confirm if this was successful.</p>
<img src='port-diagram.png' height=200px>
<img src='input-synchronization.png' height=200px>
<p><a href='../../index.html'>Back</a></p>
</body>
</html>
\ No newline at end of file
gpio/atsamd51/input-synchronization.png

183 KiB

gpio/atsamd51/port-diagram.png

109 KiB

#define portin PORT->Group[PORTA].IN.reg
#define outclr PORT->Group[PORTA].OUTCLR.reg
#define outset PORT->Group[PORTA].OUTSET.reg
#define out PORT->Group[PORTA].OUT.reg
#define outtgl PORT->Group[PORTA].OUTTGL.reg
//11: { PORTA, 21, PIO_TCC_PDEC, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_5 },
const uint8_t in_pin = 21;
const uint32_t in_mask = 1ul<<in_pin;
//12: { PORTA, 22, PIO_TCC_PDEC, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH2, TCC0_CH2, EXTERNAL_INT_6 },
const uint8_t out_pin = 22;
const uint32_t out_mask = 1ul<<out_pin;
//led:{ PORTA, 23, PIO_TCC_PDEC, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH3, TCC0_CH3, EXTERNAL_INT_7 }, // TCC2/WO[1]
//const uint32_t out_mask = 1ul<<23;
void setup() {
//set clock port for digital io
//PM->APBBMASK.reg |= PM_APBBMASK_PORT ;
// Set pin mode according to chapter '32.6.3 I/O Pin Configuration'
// enable input, to support reading back values, with pullups disabled
PORT->Group[PORTA].PINCFG[out_pin].reg = (uint8_t)(PORT_PINCFG_INEN) ;
// Set pin to output mode
PORT->Group[PORTA].DIRSET.reg = out_mask;
// Set in pin to input mode
PORT->Group[PORTA].PINCFG[in_pin].reg=(uint8_t)(PORT_PINCFG_INEN) ;
PORT->Group[PORTA].DIRCLR.reg = in_pin ;
PORT->Group[PORTA].CTRL.reg = in_mask; //make sure port synchronizer always active
while(1){
/*PORT->Group[PORTA].OUTSET.reg = out_mask; // turn on led
delay(1000); // wait for a second
PORT->Group[PORTA].OUTCLR.reg = out_mask; // turn off led
delay(1000); // wait for a second
*/
//ternary operator: assymetric 300ns (200-100)
//portin & in_mask ? outclr = out_mask : outset = out_mask;
//portin & in_mask ? outclr = out_mask : out = out_mask;
out = ~(portin);
//bitwise xor: 300ns
//out = ((portin ^ in_mask) << 1);
//if else
/*if (portin & in_mask){
outclr = out_mask;
} else {
outset = out_mask;
}*/
//toggle, 10 mhz
//outtgl = out_mask;
//manual toggle, 20mhz
//outclr = out_mask;
//outset = out_mask;
}
}
void loop() {}
gpio/atsamd51/ring.jpg

368 KiB

...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
"dev_board_sales_link":"link for dev board purchase", "dev_board_sales_link":"link for dev board purchase",
"ic_price":"price for bare ic, dollars", "ic_price":"price for bare ic, dollars",
"ic_sales_link":"link for ic purchase", "ic_sales_link":"link for ic purchase",
"cpu_frequency":"clock speed in MHz",
"ring_period":"period of one full ring oscillator waveform, in microseconds" "ring_period":"period of one full ring oscillator waveform, in microseconds"
}, },
...@@ -63,6 +64,17 @@ ...@@ -63,6 +64,17 @@
} }
], ],
"gpio":[ "gpio":[
{
"name":"ATSAMD51",
"serial_number":"",
"subdirectory_path":"gpio/atsamd51",
"dev_board_price":14.95,
"dev_board_sales link":"https://www.adafruit.com/product/3800",
"ic_price":4.31,
"ic_sales_link":"ATSAMD51J19A-AUTCT-ND",
"cpu_frequency":120,
"ring_period":0.27
},
{ {
"name":"ATSAMS70", "name":"ATSAMS70",
"serial_number":"", "serial_number":"",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment