Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/Tools/Linux_HAL_Essentials/pru/pwmpru/pwmpru1.c
Views: 1800
/*1* testpru2*3*/45#define PRU16#include <stdio.h>7#include <stdlib.h>8#include <stdarg.h>9#include <stdio.h>10#include <strings.h>1112#include "linux_types.h"13#include "pru_defs.h"14#include "prucomm.h"151617struct pwm_cmd_l cfg;1819static void pwm_setup(void)20{21u8 i;2223cfg.enmask = 0;24for (i = 0; i < MAX_PWMS; i++)25cfg.hilo[i][0] = cfg.hilo[i][1] = PRU_us(200);26}272829static inline u32 read_PIEP_COUNT(void)30{31return PIEP_COUNT;3233}3435int main(int argc, char *argv[])36{37u8 i;38u32 cnt, next;39u32 msk, setmsk, clrmsk;40u32 delta, deltamin, tnext, hi, lo;41u32 *nextp;42const u32 *hilop;43u32 period;44u32 enmask; /* enable mask */45u32 stmask; /* state mask */46static u32 next_hi_lo[MAX_PWMS][3];47static struct cxt cxt;48/* enable OCP master port */49PRUCFG_SYSCFG &= ~SYSCFG_STANDBY_INIT;50PRUCFG_SYSCFG = (PRUCFG_SYSCFG &51~(SYSCFG_IDLE_MODE_M | SYSCFG_STANDBY_MODE_M)) |52SYSCFG_IDLE_MODE_NO | SYSCFG_STANDBY_MODE_NO;5354/* our PRU wins arbitration */55PRUCFG_SPP |= SPP_PRU1_PAD_HP_EN;56pwm_setup();5758/* configure timer */59PIEP_GLOBAL_CFG = GLOBAL_CFG_DEFAULT_INC(1) |60GLOBAL_CFG_CMP_INC(1);61PIEP_CMP_STATUS = CMD_STATUS_CMP_HIT(1); /* clear the interrupt */62PIEP_CMP_CMP1 = 0x0;63PIEP_CMP_CFG |= CMP_CFG_CMP_EN(1);64PIEP_GLOBAL_CFG |= GLOBAL_CFG_CNT_ENABLE;6566/* initialize */67cnt = read_PIEP_COUNT();6869enmask = cfg.enmask;70stmask = 0; /* starting all low */7172clrmsk = 0;73for (i = 0, msk = 1, nextp = &next_hi_lo[0][0], hilop = &cfg.hilo[0][0];74i < MAX_PWMS;75i++, msk <<= 1, nextp += 3, hilop += 2) {76if ((enmask & msk) == 0) {77nextp[1] = PRU_us(100); /* default */78nextp[2] = PRU_us(100);79continue;80}81nextp[0] = cnt; /* next */82nextp[1] = 200000; /* hi */83nextp[2] = 208000; /* lo */84PWM_CMD->periodhi[i][0] = 408000;85PWM_CMD->periodhi[i][1] = 180000;86}87PWM_CMD->enmask = 0;88clrmsk = enmask;89setmsk = 0;90/* guaranteed to be immediate */91deltamin = 0;92next = cnt + deltamin;93PWM_CMD->magic = PWM_REPLY_MAGIC;9495while(1) {969798//if(PWM_CMD->magic == PWM_CMD_MAGIC)99{100msk = PWM_CMD->enmask;101for(i=0, nextp = &next_hi_lo[0][0]; i<MAX_PWMS;102i++, nextp += 3){103//Enable104if ((PWM_EN_MASK & (msk&(1U<<i))) && (enmask & (msk&(1U<<i))) == 0) {105enmask |= (msk&(1U<<i));106107__R30 |= (msk&(1U<<i));108nextp[0] = cnt; //since we start high, wait this amount109110// first enable111if (enmask == (msk&(1U<<i)))112cnt = read_PIEP_COUNT();113deltamin = 0;114next = cnt;115}116//Disable117if ((PWM_EN_MASK & (msk&(1U<<i))) && ((msk & ~(1U<<i)) == 0)) {118enmask &= ~(1U<<i);119__R30 &= ~(1U<<i);120}121122//get and set pwm_vals123if (PWM_EN_MASK & (msk&(1U<<i))) {124125//nextp = &next_hi_lo[i * 3];126nextp[1] = PWM_CMD->periodhi[i][1];127period = PWM_CMD->periodhi[i][0];128nextp[2] =period - nextp[1];129130}131PWM_CMD->hilo_read[i][0] = nextp[0];132PWM_CMD->hilo_read[i][1] = nextp[1];133134135}136137// guaranteed to be immediate138deltamin = 0;139140PWM_CMD->magic = PWM_REPLY_MAGIC;141}142PWM_CMD->enmask_read = enmask;143/* if nothing is enabled just skip it all */144if (enmask == 0)145continue;146147setmsk = 0;148clrmsk = (u32)-1;149deltamin = PRU_ms(100); /* (1U << 31) - 1; */150next = cnt + deltamin;151152#define SINGLE_PWM(_i) \153do { \154if (enmask & (1U << (_i))) { \155nextp = &next_hi_lo[(_i)][0]; \156tnext = nextp[0]; \157hi = nextp[1]; \158lo = nextp[2]; \159/* avoid signed arithmetic */ \160while (((delta = (tnext - cnt)) & (1U << 31)) != 0) { \161/* toggle the state */ \162if (stmask & (1U << (_i))) { \163stmask &= ~(1U << (_i)); \164clrmsk &= ~(1U << (_i)); \165tnext += lo; \166} else { \167stmask |= (1U << (_i)); \168setmsk |= (1U << (_i)); \169tnext += hi; \170} \171} \172if (delta <= deltamin) { \173deltamin = delta; \174next = tnext; \175} \176nextp[0] = tnext; \177} \178} while (0)179180181182#if MAX_PWMS > 0 && (PWM_EN_MASK & BIT(0))183SINGLE_PWM(0);184#endif185#if MAX_PWMS > 1 && (PWM_EN_MASK & BIT(1))186SINGLE_PWM(1);187#endif188#if MAX_PWMS > 2 && (PWM_EN_MASK & BIT(2))189SINGLE_PWM(2);190#endif191#if MAX_PWMS > 3 && (PWM_EN_MASK & BIT(3))192SINGLE_PWM(3);193#endif194#if MAX_PWMS > 4 && (PWM_EN_MASK & BIT(4))195SINGLE_PWM(4);196#endif197#if MAX_PWMS > 5 && (PWM_EN_MASK & BIT(5))198SINGLE_PWM(5);199#endif200#if MAX_PWMS > 6 && (PWM_EN_MASK & BIT(6))201SINGLE_PWM(6);202#endif203#if MAX_PWMS > 7 && (PWM_EN_MASK & BIT(7))204SINGLE_PWM(7);205#endif206#if MAX_PWMS > 8 && (PWM_EN_MASK & BIT(8))207SINGLE_PWM(8);208#endif209#if MAX_PWMS > 9 && (PWM_EN_MASK & BIT(9))210SINGLE_PWM(9);211#endif212#if MAX_PWMS > 10 && (PWM_EN_MASK & BIT(10))213SINGLE_PWM(10);214#endif215#if MAX_PWMS > 11 && (PWM_EN_MASK & BIT(11))216SINGLE_PWM(11);217#endif218#if MAX_PWMS > 12 && (PWM_EN_MASK & BIT(12))219SINGLE_PWM(12);220#endif221222/* results in set bits where there are changes */223224__R30 = (__R30 & (clrmsk & 0xfff)) | (setmsk & 0xfff);225226/* loop while nothing changes */227do {228cnt = read_PIEP_COUNT();229if(PWM_CMD->magic == PWM_CMD_MAGIC){230break;231}232} while (((next - cnt) & (1U << 31)) == 0);233}234}235236237