Skip to content
Snippets Groups Projects
Commit 1f6c04ff authored by Jake Read's avatar Jake Read
Browse files

add SPI alive and doc

parent 39617406
Branches
No related tags found
No related merge requests found
......@@ -326,4 +326,179 @@ So this shortened motor wires did seem to really kill the problem. Fin.
We're going to do this on the ATSAMD51, now. I have a v0.3 board here (which will shortly be rev'd to 0.31 due to a few already apparent mistakes, welp) and I can program it. I'm in the process of checking all of the hardware so that I can go forward with a new board order, knowing a bit better that I'll be o-k with that set.
So! I want to set up the project and check my clock settings and interrupts for good measure.
\ No newline at end of file
I've got the PWM up, and it's running as expected. Nice.
```C
int main(void)
{
/* Initialize the SAM system */
SystemInit();
PORT->Group[1].DIRSET.reg |= (uint32_t)(1 << 9);
PORT->Group[0].DIRSET.reg |= (uint32_t)(1 << 23);
SysTick_Config(5000000);
/* TCC SETUP */
// from 49.6.2.1
// a few registers are protected - and can only be updated when
// TCCn.CTRLA.ENABLE = 0
// FCTRLA and FCTRLB, WEXCTRL, DRVCTRL, and EVCTRL
// (4) Configure Output Pin with PORT->Group[n].DIRSET.reg
// PA8 PA9 PA10 PA12, PB10 PB11
// 32.9.13
PORT->Group[0].DIRSET.reg |= (uint32_t)(1 << 8) | (uint32_t)(1 << 9) | (uint32_t)(1 << 10) | (uint32_t)(1 << 12);
PORT->Group[1].DIRSET.reg |= (uint32_t)(1 << 10) | (uint32_t)(1 << 11);
// 1 lo / hi
PORT->Group[0].PINCFG[10].bit.PMUXEN = 1;
PORT->Group[0].PMUX[10>>1].reg |= PORT_PMUX_PMUXE(0x5); // on peripheral F
PORT->Group[0].PINCFG[12].bit.PMUXEN = 1;
PORT->Group[0].PMUX[12>>1].reg |= PORT_PMUX_PMUXE(0x5);
// 2 lo / hi
PORT->Group[0].PINCFG[9].bit.PMUXEN = 1;
PORT->Group[0].PMUX[9>>1].reg |= PORT_PMUX_PMUXO(0x5); // on peripheral F
PORT->Group[1].PINCFG[11].bit.PMUXEN = 1;
PORT->Group[1].PMUX[11>>1].reg |= PORT_PMUX_PMUXO(0x5);
// 3 lo / hi
PORT->Group[0].PINCFG[8].bit.PMUXEN = 1;
PORT->Group[0].PMUX[8>>1].reg |= PORT_PMUX_PMUXE(0x5); // on peripheral F
PORT->Group[1].PINCFG[10].bit.PMUXEN = 1;
PORT->Group[1].PMUX[10>>1].reg |= PORT_PMUX_PMUXE(0x5);
// (1) enable the TCC Bus Clock - CLK_TCCn_APB
// https://www.eevblog.com/forum/microcontrollers/atmel-sam-d-tc-and-tcc-(no-asf)/
TCC0->CTRLA.bit.ENABLE = 0;
MCLK->APBBMASK.reg |= MCLK_APBBMASK_TCC0; // at 15.8.9
GCLK->GENCTRL[5].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_DFLL) | GCLK_GENCTRL_GENEN;
while(GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL5);
GCLK->PCHCTRL[TCC0_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK5;
TCC0->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV8 | TCC_CTRLA_PRESCSYNC_PRESC |TCC_CTRLA_RESOLUTION(0);
// (2) Select Waveform Generation operation in the WAVE register WAVE.WAVEGEN
// we want dual slope pwm
TCC0->WAVE.reg = TCC_WAVE_WAVEGEN_DSBOTH; // 'dual slope both' - updates on both hi and lo of slope ?
// (3) We want OTMX - Output Matrix Channel Pin Routing Configuration - at 0x0
TCC0->WEXCTRL.reg = TCC_WEXCTRL_DTHS(1) | TCC_WEXCTRL_DTLS(1) |
TCC_WEXCTRL_DTIEN1 | TCC_WEXCTRL_DTIEN2 | TCC_WEXCTRL_DTIEN3 | TCC_WEXCTRL_DTIEN0 |
TCC_WEXCTRL_OTMX(0);
TCC0->PER.reg = TCC_PER_PER(256); // 18 bit
TCC0->COUNT.reg = 0;
TCC0->CC[0].reg = 12; // '3'
TCC0->CC[1].reg = 24; // '2'
TCC0->CC[2].reg = 48; // '1'
TCC0->CC[3].reg = 0;
// (4) Enable with CTRLA.ENABLE
TCC0->CTRLA.bit.ENABLE = 1;
while(TCC0->SYNCBUSY.bit.ENABLE);
while (1)
{
PORT->Group[1].OUTTGL.reg = (uint32_t)(1 << 9);
}
}
```
![atsamd51 pwm](https://gitlab.cba.mit.edu/jakeread/mkbldcdriver/raw/master/images/programming-pwm-alive-atsamd51.png)
![atsamd51 pwm](https://gitlab.cba.mit.edu/jakeread/mkbldcdriver/raw/master/images/programming-pwm-alive-atsamd51-picture.jpg)
Next up is the SPI wakeup.
Great, this is running as well.
```C
int main(void)
{
/* Initialize the SAM system */
SystemInit();
PORT->Group[1].DIRSET.reg |= (uint32_t)(1 << 9);
PORT->Group[0].DIRSET.reg |= (uint32_t)(1 << 23);
SysTick_Config(5000000);
/* BEGIN SPI SETUP */
// PA04, SER0-0, SPI_MISO
// PA05, SER0-1, SPI_SCK
// PA06, SER0-2, SPI_CSN
// PA07, SER0-3, SPI_MOSI
PORT->Group[0].DIRCLR.reg |= (uint32_t)(1 << 4);
PORT->Group[0].DIRSET.reg |= (uint32_t)(1 << 5) | (uint32_t)(1 << 6) | (uint32_t)(1 << 7);
PORT->Group[0].PINCFG[4].bit.PMUXEN = 1;
PORT->Group[0].PMUX[4>>1].reg |= PORT_PMUX_PMUXE(0x3); // on peripheral D
PORT->Group[0].PINCFG[5].bit.PMUXEN = 1;
PORT->Group[0].PMUX[5>>1].reg |= PORT_PMUX_PMUXO(0x3); // on peripheral D
PORT->Group[0].PINCFG[6].bit.PMUXEN = 1;
PORT->Group[0].PMUX[6>>1].reg |= PORT_PMUX_PMUXE(0x3); // on peripheral D
PORT->Group[0].PINCFG[7].bit.PMUXEN = 1;
PORT->Group[0].PMUX[7>>1].reg |= PORT_PMUX_PMUXO(0x3); // on peripheral D
// setup clocks to sercom
MCLK->APBAMASK.reg |= MCLK_APBAMASK_SERCOM0; // at 15.8.9
GCLK->GENCTRL[6].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_DFLL) | GCLK_GENCTRL_GENEN;
while(GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL6);
GCLK->PCHCTRL[SERCOM0_GCLK_ID_CORE].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK6;
// TCC0_GCLK_ID
// Some registers can't be written unless CTRL.ENABLE = 0:
// CTRLA, CTRLB, BAD and ADDR
// (1) set to master
SERCOM0->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_MODE(0x3); // 0x2 or 0x3, slave or master
// SERCOM0->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_CPHA | SERCOM_SPI_CTRLA_CPOL; // clock phase and polarity
// (2) set pin configurations
SERCOM0->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_DIPO(0x0) | SERCOM_SPI_CTRLA_DOPO(0x2); // pin selections, see 35.8.1 bits 21:20 and 17:16, pg. 910
// (3) set character size, data direction
//SERCOM0->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_DORD; // 0 MSB, 1 LSB
//SERCOM0->SPI.CTRLB.reg |= SERCOM_SPI_CTRLB_CHSIZE(0x0); // 8 bits character - 0x0, so no need to set
// (4) setup baud rate
// f_baud = f_ref / (2 * (BAUD +1)) so BAUD = f_ref / (2 * f_baud) - 1
SERCOM0->SPI.BAUD.reg |= SERCOM_SPI_BAUD_BAUD(126);
SERCOM0->SPI.CTRLB.reg |= SERCOM_SPI_CTRLB_MSSEN | SERCOM_SPI_CTRLB_RXEN; // slave select hardware yes
SERCOM0->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_ENABLE;
while (1)
{
while(!(SERCOM0->SPI.INTFLAG.bit.DRE));
SERCOM0->SPI.DATA.reg = SERCOM_SPI_DATA_DATA(80);
PORT->Group[1].OUTTGL.reg = (uint32_t)(1 << 9); // i-v, to check we made it thru setup
}
}
```
![atsamd51 spi](https://gitlab.cba.mit.edu/jakeread/mkbldcdriver/raw/master/images/programming-spi-alive-atsamd51.png)
Now we do v0.31 board, new step board, etc. Go team, big day.
\ No newline at end of file
No preview for this file type
......@@ -11,16 +11,7 @@
// stlb is PA23
int main(void)
{
/* Initialize the SAM system */
SystemInit();
PORT->Group[1].DIRSET.reg |= (uint32_t)(1 << 9);
PORT->Group[0].DIRSET.reg |= (uint32_t)(1 << 23);
SysTick_Config(5000000);
void pwmsetup(void){
/* TCC SETUP */
// from 49.6.2.1
// a few registers are protected - and can only be updated when
......@@ -80,19 +71,93 @@ int main(void)
TCC0->COUNT.reg = 0;
TCC0->CC[0].reg = 12; // '3'
TCC0->CC[1].reg = 24; // '2'
TCC0->CC[2].reg = 48; // '1'
TCC0->CC[0].reg = 0; // '3'
TCC0->CC[1].reg = 0; // '2'
TCC0->CC[2].reg = 0; // '1'
TCC0->CC[3].reg = 0;
// (4) Enable with CTRLA.ENABLE
TCC0->CTRLA.bit.ENABLE = 1;
while(TCC0->SYNCBUSY.bit.ENABLE);
}
void pwmupdate(uint32_t one, uint32_t two, uint32_t three){
TCC0->CC[0].reg = three; // '3'
TCC0->CC[1].reg = two; // '2'
TCC0->CC[2].reg = one; // '1'
}
int main(void)
{
/* Initialize the SAM system */
SystemInit();
PORT->Group[1].DIRSET.reg |= (uint32_t)(1 << 9);
PORT->Group[0].DIRSET.reg |= (uint32_t)(1 << 23);
SysTick_Config(5000000);
/* BEGIN SPI SETUP */
// PA04, SER0-0, SPI_MISO
// PA05, SER0-1, SPI_SCK
// PA06, SER0-2, SPI_CSN
// PA07, SER0-3, SPI_MOSI
PORT->Group[0].DIRCLR.reg |= (uint32_t)(1 << 4);
PORT->Group[0].DIRSET.reg |= (uint32_t)(1 << 5) | (uint32_t)(1 << 6) | (uint32_t)(1 << 7);
PORT->Group[0].PINCFG[4].bit.PMUXEN = 1;
PORT->Group[0].PMUX[4>>1].reg |= PORT_PMUX_PMUXE(0x3); // on peripheral D
PORT->Group[0].PINCFG[5].bit.PMUXEN = 1;
PORT->Group[0].PMUX[5>>1].reg |= PORT_PMUX_PMUXO(0x3); // on peripheral D
PORT->Group[0].PINCFG[6].bit.PMUXEN = 1;
PORT->Group[0].PMUX[6>>1].reg |= PORT_PMUX_PMUXE(0x3); // on peripheral D
PORT->Group[0].PINCFG[7].bit.PMUXEN = 1;
PORT->Group[0].PMUX[7>>1].reg |= PORT_PMUX_PMUXO(0x3); // on peripheral D
// setup clocks to sercom
MCLK->APBAMASK.reg |= MCLK_APBAMASK_SERCOM0; // at 15.8.9
GCLK->GENCTRL[6].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_DFLL) | GCLK_GENCTRL_GENEN;
while(GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL6);
GCLK->PCHCTRL[SERCOM0_GCLK_ID_CORE].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK6;
// TCC0_GCLK_ID
// Some registers can't be written unless CTRL.ENABLE = 0:
// CTRLA, CTRLB, BAD and ADDR
// (1) set to master
SERCOM0->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_MODE(0x3); // 0x2 or 0x3, slave or master
// SERCOM0->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_CPHA | SERCOM_SPI_CTRLA_CPOL; // clock phase and polarity
// (2) set pin configurations
SERCOM0->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_DIPO(0x0) | SERCOM_SPI_CTRLA_DOPO(0x2); // pin selections, see 35.8.1 bits 21:20 and 17:16, pg. 910
// (3) set character size, data direction
//SERCOM0->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_DORD; // 0 MSB, 1 LSB
//SERCOM0->SPI.CTRLB.reg |= SERCOM_SPI_CTRLB_CHSIZE(0x0); // 8 bits character - 0x0, so no need to set
// (4) setup baud rate
// f_baud = f_ref / (2 * (BAUD +1)) so BAUD = f_ref / (2 * f_baud) - 1
SERCOM0->SPI.BAUD.reg |= SERCOM_SPI_BAUD_BAUD(126);
SERCOM0->SPI.CTRLB.reg |= SERCOM_SPI_CTRLB_MSSEN | SERCOM_SPI_CTRLB_RXEN; // slave select hardware yes
SERCOM0->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_ENABLE;
while (1)
{
PORT->Group[1].OUTTGL.reg = (uint32_t)(1 << 9);
while(!(SERCOM0->SPI.INTFLAG.bit.DRE));
SERCOM0->SPI.DATA.reg = SERCOM_SPI_DATA_DATA(80);
PORT->Group[1].OUTTGL.reg = (uint32_t)(1 << 9); // i-v, to check we made it thru setup
}
}
......
images/programming-pwm-alive-atsamd51-picture.jpg

325 KiB

images/programming-pwm-alive-atsamd51.png

93.5 KiB

images/programming-spi-alive-atsamd51.png

113 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment