diff --git a/embedded/README.md b/embedded/README.md index 8a7aa74a714c7dfaf5536b713450b1d07f2f95b5..275f667ecfd99dd3ef48e41a9d50532133d65c98 100644 --- a/embedded/README.md +++ b/embedded/README.md @@ -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); + } +} +``` + + + + + +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 + } +} +``` + + + +Now we do v0.31 board, new step board, etc. Go team, big day. \ No newline at end of file diff --git a/embedded/mkbldcdriver-v03/.vs/mkbldcdriver-v03/v14/.atsuo b/embedded/mkbldcdriver-v03/.vs/mkbldcdriver-v03/v14/.atsuo index 091e0e9973aa6d32a1ff82f521bfff5bf040ee90..6cb941a9f4c80642687368b0956373ae5910d32a 100644 Binary files a/embedded/mkbldcdriver-v03/.vs/mkbldcdriver-v03/v14/.atsuo and b/embedded/mkbldcdriver-v03/.vs/mkbldcdriver-v03/v14/.atsuo differ diff --git a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/main.c b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/main.c index a046b9826cba51795646176dce7602d9b906dde6..5fb245e181e7ae4c5b61d869b2db8e73972cc469 100644 --- a/embedded/mkbldcdriver-v03/mkbldcdriver-v03/main.c +++ b/embedded/mkbldcdriver-v03/mkbldcdriver-v03/main.c @@ -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 } } diff --git a/images/programming-pwm-alive-atsamd51-picture.jpg b/images/programming-pwm-alive-atsamd51-picture.jpg new file mode 100644 index 0000000000000000000000000000000000000000..448c0937c023dd6756f9c98f1a6d7564e6a521f9 Binary files /dev/null and b/images/programming-pwm-alive-atsamd51-picture.jpg differ diff --git a/images/programming-pwm-alive-atsamd51.png b/images/programming-pwm-alive-atsamd51.png new file mode 100644 index 0000000000000000000000000000000000000000..6dca6d5ffdcaa1bdd919335d2c4ed11ff3afedb4 Binary files /dev/null and b/images/programming-pwm-alive-atsamd51.png differ diff --git a/images/programming-spi-alive-atsamd51.png b/images/programming-spi-alive-atsamd51.png new file mode 100644 index 0000000000000000000000000000000000000000..eef6050dd32c2dd59ee0fa5b2c93604e7d0ff29d Binary files /dev/null and b/images/programming-spi-alive-atsamd51.png differ