diff --git a/.bazelignore b/.bazelignore new file mode 100644 index 0000000..533e957 --- /dev/null +++ b/.bazelignore @@ -0,0 +1 @@ +kernel diff --git a/arch/am335x/BUILD b/arch/am335x/BUILD new file mode 100644 index 0000000..832ae67 --- /dev/null +++ b/arch/am335x/BUILD @@ -0,0 +1,18 @@ +# -*- Mode: Python -*- +package(default_visibility = ["//visibility:public"]) + +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +filegroup( + name = "defs", + srcs = glob(["*.csv"]), +) + +go_library( + name = "am335x", + srcs = ["embed.go"], + embedsrcs = [ + ":defs", + ], + importpath = "github.com/jmacd/supruglue/arch/am335x", +) diff --git a/arch/am335x/am335x-map.csv b/arch/am335x/am335x-map.csv new file mode 100644 index 0000000..829189a --- /dev/null +++ b/arch/am335x/am335x-map.csv @@ -0,0 +1,16 @@ +Module,Base,Unit,Layout +pwmss-epwm0,0x4830_0200,2,pwmss-epwm +pwmss-epwm1,0x4830_2200,2,pwmss-epwm +pwmss-epwm2,0x4830_4200,2,pwmss-epwm +pwmss-ecap0,0x4830_0100,2,pwmss-ecap +pwmss-ecap1,0x4830_2100,2,pwmss-ecap +pwmss-ecap2,0x4830_4100,2,pwmss-ecap +pwmss0,0x4830_0000,4,pwmss +pwmss1,0x4830_2000,4,pwmss +pwmss2,0x4830_4000,4,pwmss +edma-tpcc,0x4900_0000,4,edma-tpcc +soc-ctrl,0x44E1_0000,4,soc-ctrl +clock-per,0x44E0_0000,4,clock-per +pru-intc,0x4A32_0000,4,pru-intc +pru-iep,0x4A32_E000,4,pru-iep +pru-ecap,0x4A33_0000,2,pwmss-ecap diff --git a/arch/am335x/clock-per.csv b/arch/am335x/clock-per.csv new file mode 100644 index 0000000..95a2caa --- /dev/null +++ b/arch/am335x/clock-per.csv @@ -0,0 +1,59 @@ +Offset,Name,Description +0h,CM_PER_L4LS_CLKSTCTRL, +4h,CM_PER_L3S_CLKSTCTRL, +Ch,CM_PER_L3_CLKSTCTRL, +14h,CM_PER_CPGMAC0_CLKCTRL, +18h,CM_PER_LCDC_CLKCTRL, +1Ch,CM_PER_USB0_CLKCTRL, +24h,CM_PER_TPTC0_CLKCTRL, +28h,CM_PER_EMIF_CLKCTRL, +2Ch,CM_PER_OCMCRAM_CLKCTRL, +30h,CM_PER_GPMC_CLKCTRL, +34h,CM_PER_MCASP0_CLKCTRL, +38h,CM_PER_UART5_CLKCTRL, +3Ch,CM_PER_MMC0_CLKCTRL, +40h,CM_PER_ELM_CLKCTRL, +44h,CM_PER_I2C2_CLKCTRL, +48h,CM_PER_I2C1_CLKCTRL, +4Ch,CM_PER_SPI0_CLKCTRL, +50h,CM_PER_SPI1_CLKCTRL, +60h,CM_PER_L4LS_CLKCTRL, +68h,CM_PER_MCASP1_CLKCTRL, +6Ch,CM_PER_UART1_CLKCTRL, +70h,CM_PER_UART2_CLKCTRL, +74h,CM_PER_UART3_CLKCTRL, +78h,CM_PER_UART4_CLKCTRL, +7Ch,CM_PER_TIMER7_CLKCTRL, +80h,CM_PER_TIMER2_CLKCTRL, +84h,CM_PER_TIMER3_CLKCTRL, +88h,CM_PER_TIMER4_CLKCTRL, +ACh,CM_PER_GPIO1_CLKCTRL, +B0h,CM_PER_GPIO2_CLKCTRL, +B4h,CM_PER_GPIO3_CLKCTRL, +BCh,CM_PER_TPCC_CLKCTRL, +C0h,CM_PER_DCAN0_CLKCTRL, +C4h,CM_PER_DCAN1_CLKCTRL, +CCh,CM_PER_EPWMSS1_CLKCTRL, +D4h,CM_PER_EPWMSS0_CLKCTRL, +D8h,CM_PER_EPWMSS2_CLKCTRL, +DCh,CM_PER_L3_INSTR_CLKCTRL, +E0h,CM_PER_L3_CLKCTRL, +E4h,CM_PER_IEEE5000_CLKCTRL, +E8h,CM_PER_PRU_ICSS_CLKCTRL, +ECh,CM_PER_TIMER5_CLKCTRL, +F0h,CM_PER_TIMER6_CLKCTRL, +F4h,CM_PER_MMC1_CLKCTRL, +F8h,CM_PER_MMC2_CLKCTRL, +FCh,CM_PER_TPTC1_CLKCTRL, +100h,CM_PER_TPTC2_CLKCTRL, +10Ch,CM_PER_SPINLOCK_CLKCTRL, +110h,CM_PER_MAILBOX0_CLKCTRL, +11Ch,CM_PER_L4HS_CLKSTCTRL, +120h,CM_PER_L4HS_CLKCTRL, +12Ch,CM_PER_OCPWP_L3_CLKSTCTRL, +130h,CM_PER_OCPWP_CLKCTRL, +140h,CM_PER_PRU_ICSS_CLKSTCTRL, +144h,CM_PER_CPSW_CLKSTCTRL, +148h,CM_PER_LCDC_CLKSTCTRL, +14Ch,CM_PER_CLKDIV32K_CLKCTRL, +150h,CM_PER_CLK_24MHZ_CLKSTCTRL, diff --git a/arch/am335x/edma-tpcc.csv b/arch/am335x/edma-tpcc.csv new file mode 100644 index 0000000..8b1d830 --- /dev/null +++ b/arch/am335x/edma-tpcc.csv @@ -0,0 +1,203 @@ +Offset,Name,Description +0h,PID,Peripheral Identification Register +4h,CCCFG,EDMA3CC Configuration Register +10h,SYSCONFIG,EDMA3CC System Configuration Register +100h,DCHMAP_0,DMA Channel Mapping Register 0 +104h,DCHMAP_1,DMA Channel Mapping Register 1 +108h,DCHMAP_2,DMA Channel Mapping Register 2 +10Ch,DCHMAP_3,DMA Channel Mapping Register 3 +110h,DCHMAP_4,DMA Channel Mapping Register 4 +114h,DCHMAP_5,DMA Channel Mapping Register 5 +118h,DCHMAP_6,DMA Channel Mapping Register 6 +11Ch,DCHMAP_7,DMA Channel Mapping Register 7 +120h,DCHMAP_8,DMA Channel Mapping Register 8 +124h,DCHMAP_9,DMA Channel Mapping Register 9 +128h,DCHMAP_10,DMA Channel Mapping Register 10 +12Ch,DCHMAP_11,DMA Channel Mapping Register 11 +130h,DCHMAP_12,DMA Channel Mapping Register 12 +134h,DCHMAP_13,DMA Channel Mapping Register 13 +138h,DCHMAP_14,DMA Channel Mapping Register 14 +13Ch,DCHMAP_15,DMA Channel Mapping Register 15 +140h,DCHMAP_16,DMA Channel Mapping Register 16 +144h,DCHMAP_17,DMA Channel Mapping Register 17 +148h,DCHMAP_18,DMA Channel Mapping Register 18 +14Ch,DCHMAP_19,DMA Channel Mapping Register 19 +150h,DCHMAP_20,DMA Channel Mapping Register 20 +154h,DCHMAP_21,DMA Channel Mapping Register 21 +158h,DCHMAP_22,DMA Channel Mapping Register 22 +15Ch,DCHMAP_23,DMA Channel Mapping Register 23 +160h,DCHMAP_24,DMA Channel Mapping Register 24 +164h,DCHMAP_25,DMA Channel Mapping Register 25 +168h,DCHMAP_26,DMA Channel Mapping Register 26 +16Ch,DCHMAP_27,DMA Channel Mapping Register 27 +170h,DCHMAP_28,DMA Channel Mapping Register 28 +174h,DCHMAP_29,DMA Channel Mapping Register 29 +178h,DCHMAP_30,DMA Channel Mapping Register 30 +17Ch,DCHMAP_31,DMA Channel Mapping Register 31 +180h,DCHMAP_32,DMA Channel Mapping Register 32 +184h,DCHMAP_33,DMA Channel Mapping Register 33 +188h,DCHMAP_34,DMA Channel Mapping Register 34 +18Ch,DCHMAP_35,DMA Channel Mapping Register 35 +190h,DCHMAP_36,DMA Channel Mapping Register 36 +194h,DCHMAP_37,DMA Channel Mapping Register 37 +198h,DCHMAP_38,DMA Channel Mapping Register 38 +19Ch,DCHMAP_39,DMA Channel Mapping Register 39 +1A0h,DCHMAP_40,DMA Channel Mapping Register 40 +1A4h,DCHMAP_41,DMA Channel Mapping Register 41 +1A8h,DCHMAP_42,DMA Channel Mapping Register 42 +1ACh,DCHMAP_43,DMA Channel Mapping Register 43 +1B0h,DCHMAP_44,DMA Channel Mapping Register 44 +1B4h,DCHMAP_45,DMA Channel Mapping Register 45 +1B8h,DCHMAP_46,DMA Channel Mapping Register 46 +1BCh,DCHMAP_47,DMA Channel Mapping Register 47 +1C0h,DCHMAP_48,DMA Channel Mapping Register 48 +1C4h,DCHMAP_49,DMA Channel Mapping Register 49 +1C8h,DCHMAP_50,DMA Channel Mapping Register 50 +1CCh,DCHMAP_51,DMA Channel Mapping Register 51 +1D0h,DCHMAP_52,DMA Channel Mapping Register 52 +1D4h,DCHMAP_53,DMA Channel Mapping Register 53 +1D8h,DCHMAP_54,DMA Channel Mapping Register 54 +1DCh,DCHMAP_55,DMA Channel Mapping Register 55 +1E0h,DCHMAP_56,DMA Channel Mapping Register 56 +1E4h,DCHMAP_57,DMA Channel Mapping Register 57 +1E8h,DCHMAP_58,DMA Channel Mapping Register 58 +1ECh,DCHMAP_59,DMA Channel Mapping Register 59 +1F0h,DCHMAP_60,DMA Channel Mapping Register 60 +1F4h,DCHMAP_61,DMA Channel Mapping Register 61 +1F8h,DCHMAP_62,DMA Channel Mapping Register 62 +1FCh,DCHMAP_63,DMA Channel Mapping Register 63 +200h,QCHMAP_0,QDMA Channel Mapping Register 0 +204h,QCHMAP_1,QDMA Channel Mapping Register 1 +208h,QCHMAP_2,QDMA Channel Mapping Register 2 +20Ch,QCHMAP_3,QDMA Channel Mapping Register 3 +210h,QCHMAP_4,QDMA Channel Mapping Register 4 +214h,QCHMAP_5,QDMA Channel Mapping Register 5 +218h,QCHMAP_6,QDMA Channel Mapping Register 6 +21Ch,QCHMAP_7,QDMA Channel Mapping Register 7 +240h,DMAQNUM_0,DMA Queue Number Register 0 +244h,DMAQNUM_1,DMA Queue Number Register 1 +248h,DMAQNUM_2,DMA Queue Number Register 2 +24Ch,DMAQNUM_3,DMA Queue Number Register 3 +250h,DMAQNUM_4,DMA Queue Number Register 4 +254h,DMAQNUM_5,DMA Queue Number Register 5 +258h,DMAQNUM_6,DMA Queue Number Register 6 +25Ch,DMAQNUM_7,DMA Queue Number Register 7 +260h,QDMAQNUM,QDMA Queue Number Register +284h,QUEPRI,Queue Priority Register +300h,EMR,Event Missed Register +304h,EMRH,Event Missed Register High +308h,EMCR,Event Missed Clear Register +30Ch,EMCRH,Event Missed Clear Register High +310h,QEMR,QDMA Event Missed Register +314h,QEMCR,QDMA Event Missed Clear Register +318h,CCERR,EDMA3CC Error Register +31Ch,CCERRCLR,EDMA3CC Error Clear Register +320h,EEVAL,Error Evaluate Register +340h,DRAE0,DMA Region Access Enable Register for Region 0 +344h,DRAEH0,DMA Region Access Enable Register High for Region 0 +348h,DRAE1,DMA Region Access Enable Register for Region 1 +34Ch,DRAEH1,DMA Region Access Enable Register High for Region 1 +350h,DRAE2,DMA Region Access Enable Register for Region 2 +354h,DRAEH2,DMA Region Access Enable Register High for Region 2 +358h,DRAE3,DMA Region Access Enable Register for Region 3 +35Ch,DRAEH3,DMA Region Access Enable Register High for Region 3 +380h,QRAE_0,QDMA Region Access Enable Register for Region 0 +384h,QRAE_1,QDMA Region Access Enable Register for Region 1 +388h,QRAE_2,QDMA Region Access Enable Register for Region 2 +38Ch,QRAE_3,QDMA Region Access Enable Register for Region 3 +400h,Q0E0,Event Queue 0 Entry 0 +404h,Q0E1,Event Queue 0 Entry 1 +408h,Q0E2,Event Queue 0 Entry 2 +40Ch,Q0E3,Event Queue 0 Entry 3 +410h,Q0E4,Event Queue 0 Entry 4 +414h,Q0E5,Event Queue 0 Entry 5 +418h,Q0E6,Event Queue 0 Entry 6 +41Ch,Q0E7,Event Queue 0 Entry 7 +420h,Q0E8,Event Queue 0 Entry 8 +424h,Q0E9,Event Queue 0 Entry 9 +428h,Q0E10,Event Queue 0 Entry 10 +42Ch,Q0E11,Event Queue 0 Entry 11 +430h,Q0E12,Event Queue 0 Entry 12 +434h,Q0E13,Event Queue 0 Entry 13 +438h,Q0E14,Event Queue 0 Entry 14 +43Ch,Q0E15,Event Queue 0 Entry 15 +440h,Q1E0,Event Queue 1 Entry 0 +444h,Q1E1,Event Queue 1 Entry 1 +448h,Q1E2,Event Queue 1 Entry 2 +44Ch,Q1E3,Event Queue 1 Entry 3 +450h,Q1E4,Event Queue 1 Entry 4 +454h,Q1E5,Event Queue 1 Entry 5 +458h,Q1E6,Event Queue 1 Entry 6 +45Ch,Q1E7,Event Queue 1 Entry 7 +460h,Q1E8,Event Queue 1 Entry 8 +464h,Q1E9,Event Queue 1 Entry 9 +468h,Q1E10,Event Queue 1 Entry 10 +46Ch,Q1E11,Event Queue 1 Entry 11 +470h,Q1E12,Event Queue 1 Entry 12 +474h,Q1E13,Event Queue 1 Entry 13 +478h,Q1E14,Event Queue 1 Entry 14 +47Ch,Q1E15,Event Queue 1 Entry 15 +480h,Q2E0,Event Queue 2 Entry 0 +484h,Q2E1,Event Queue 2 Entry 1 +488h,Q2E2,Event Queue 2 Entry 2 +48Ch,Q2E3,Event Queue 2 Entry 3 +490h,Q2E4,Event Queue 2 Entry 4 +494h,Q2E5,Event Queue 2 Entry 5 +498h,Q2E6,Event Queue 2 Entry 6 +49Ch,Q2E7,Event Queue 2 Entry 7 +4A0h,Q2E8,Event Queue 2 Entry 8 +4A4h,Q2E9,Event Queue 2 Entry 9 +4A8h,Q2E10,Event Queue 2 Entry 10 +4ACh,Q2E11,Event Queue 2 Entry 11 +4B0h,Q2E12,Event Queue 2 Entry 12 +4B4h,Q2E13,Event Queue 2 Entry 13 +4B8h,Q2E14,Event Queue 2 Entry 14 +4BCh,Q2E15,Event Queue 2 Entry 15 +600h,QSTAT_0,Queue Status Register 0 +604h,QSTAT_1,Queue Status Register 1 +608h,QSTAT_2,Queue Status Register 2 +620h,QWMTHRA,Queue Watermark Threshold A Register +640h,CCSTAT,EDMA3CC Status Register +800h,MPFAR,Memory Protection Fault Address Register +804h,MPFSR,Memory Protection Fault Status Register +808h,MPFCR,Memory Protection Fault Command Register +80Ch,MPPAG,Memory Protection Page Attribute Register +810h,MPPA_0,Global Memory Protection Page Attribute Register for Region 0 +814h,MPPA_1,Global Memory Protection Page Attribute Register for Region 1 +818h,MPPA_2,Global Memory Protection Page Attribute Register for Region 2 +81Ch,MPPA_3,Global Memory Protection Page Attribute Register for Region 3 +1000h,ER,Event Register +1004h,ERH,Event Register High +1008h,ECR,Event Clear Register +100Ch,ECRH,Event Clear Register High +1010h,ESR,Event Set Register +1014h,ESRH,Event Set Register High +1018h,CER,Chained Event Register +101Ch,CERH,Chained Event Register High +1020h,EER,Event Enable Register +1024h,EERH,Event Enable Register High +1028h,EECR,Event Enable Clear Register +102Ch,EECRH,Event Enable Clear Register High +1030h,EESR,Event Enable Set Register +1034h,EESRH,Event Enable Set Register High +1038h,SER,Secondary Event Register +103Ch,SERH,Secondary Event Register High +1040h,SECR,Secondary Event Clear Register +1044h,SECRH,Secondary Event Clear Register High +1050h,IER,Interrupt Enable Register +1054h,IERH,Interrupt Enable Register High +1058h,IECR,Interrupt Enable Clear Register +105Ch,IECRH,Interrupt Enable Clear Register High +1060h,IESR,Interrupt Enable Set Register +1064h,IESRH,Interrupt Enable Set Register High +1068h,IPR,Interrupt Pending Register +106Ch,IPRH,Interrupt Pending Register High +1070h,ICR,Interrupt Clear Register +1074h,ICRH,Interrupt Clear Register High +1078h,IEVAL,Interrupt Evaluate Register +1080h,QER,QDMA Event Register +1084h,QEER,QDMA Event Enable Register +1088h,QEECR,QDMA Event Enable Clear Register +108Ch,QEESR,QDMA Event Enable Set Register +1090h,QSER,QDMA Secondary Event Register +1094h,QSECR,QDMA Secondary Event Clear Register diff --git a/arch/am335x/embed.go b/arch/am335x/embed.go new file mode 100644 index 0000000..294d64d --- /dev/null +++ b/arch/am335x/embed.go @@ -0,0 +1,32 @@ +package am335x + +import ( + "embed" + "fmt" +) + +//go:embed *.csv +var FS embed.FS + +func helper() { + for i := 0; i < 64; i++ { + fmt.Printf("%Xh,DCHMAP_%d,DMA Channel Mapping Register %d\n", i*4+0x100, i, i) + } + for i := 0; i < 8; i++ { + fmt.Printf("%Xh,QCHMAP_%d,QDMA Channel Mapping Register %d\n", i*4+0x200, i, i) + } + for i := 0; i < 8; i++ { + fmt.Printf("%Xh,DMAQNUM_%d,DMA Queue Number Register %d\n", i*4+0x240, i, i) + } + for i := 0; i < 8; i++ { + fmt.Printf("%Xh,QRAE_%d,QDMA Region access Enable Register for Region %d\n", i*4+0x380, i, i) + } + for q := 0; q < 3; q++ { + for i := 0; i < 16; i++ { + fmt.Printf("%Xh,Q%dE%d,Event Queue %d Entry %d\n", (q*16+i)*4+0x400, q, i, q, i) + } + } + for i := 0; i < 8; i++ { + fmt.Printf("%Xh,MPPA_%d,Global Memory Protection Page Attribute Register for Region %d\n", i*4+0x810, i, i) + } +} diff --git a/arch/am335x/pru-iep.csv b/arch/am335x/pru-iep.csv new file mode 100644 index 0000000..9f89f8b --- /dev/null +++ b/arch/am335x/pru-iep.csv @@ -0,0 +1,49 @@ +Offset,Name,Description +0h,IEP_TMR_GLB_CFG, +4h,IEP_TMR_GLB_STS, +8h,IEP_TMR_COMPEN, +Ch,IEP_TMR_CNT, +10h,IEP_TMR_CAP_CFG, +14h,IEP_TMR_CAP_STS, +18h,IEP_TMR_CAPR0, +1Ch,IEP_TMR_CAPR1, +20h,IEP_TMR_CAPR2, +24h,IEP_TMR_CAPR3, +28h,IEP_TMR_CAPR4, +2Ch,IEP_TMR_CAPR5, +30h,IEP_TMR_CAPR6, +34h,IEP_TMR_CAPF6, +38h,IEP_TMR_CAPR7, +3Ch,IEP_TMR_CAPF7, +40h,IEP_TMR_CMP_CFG, +44h,IEP_TMR_CMP_STS, +48h,IEP_TMR_CMP0, +4Ch,IEP_TMR_CMP1, +50h,IEP_TMR_CMP2, +54h,IEP_TMR_CMP3, +58h,IEP_TMR_CMP4, +5Ch,IEP_TMR_CMP5, +60h,IEP_TMR_CMP6, +64h,IEP_TMR_CMP7, +80h,IEP_TMR_RXIPG0, +84h,IEP_TMR_RXIPG1, +100h,IEP_SYNC_CTRL, +104h,IEP_SYNC_FIRST_STAT, +108h,IEP_SYNC0_STAT, +10Ch,IEP_SYNC1_STAT, +110h,IEP_SYNC_PWIDTH, +114h,IEP_SYNC0_PERIOD, +118h,IEP_SYNC1_DELAY, +11Ch,IEP_SYNC_START, +200h,IEP_WD_PREDIV, +204h,IEP_PDI_WD_TIM, +208h,IEP_PD_WD_TIM, +20Ch,IEP_WD_STATUS, +210h,IEP_WD_EXP_CNT, +214h,IEP_WD_CTRL, +300h,IEP_DIGIO_CTRL, +308h,IEP_DIGIO_DATA_IN, +30Ch,IEP_DIGIO_DATA_IN_RAW, +310h,IEP_DIGIO_DATA_OUT, +314h,IEP_DIGIO_DATA_OUT_EN, +318h,IEP_DIGIO_EXP, diff --git a/arch/am335x/pru-intc.csv b/arch/am335x/pru-intc.csv new file mode 100644 index 0000000..f1244f5 --- /dev/null +++ b/arch/am335x/pru-intc.csv @@ -0,0 +1,64 @@ +Offset,Name,Description +0h,REVID,Revision ID Register +4h,CR,Control Register +10h,GER,Global Host Interrupt Enable Register +1Ch,GNLR,Global Nesting Level Register +20h,SISR,System Event Status Indexed Set Register +24h,SICR,System Event Status Indexed Clear Register +28h,EISR,System Event Enable Indexed Set Register +2Ch,EICR,System Event Enable Indexed Clear Register +34h,HIEISR,Host Interrupt Enable Indexed Set Register +38h,HIDISR,Host Interrupt Enable Indexed Clear Register +80h,GPIR,Global Prioritized Index Register +200h,SRSR0,System Event Status Raw/Set Register0 +204h,SRSR1,System Event Status Raw/Set Register1 +280h,SECR0,System Event Status Enabled/Clear Register0 +284h,SECR1,System Event Status Enabled/Clear Register1 +300h,ESR0,System Event Enable Set Register0 +304h,ESR1,System Event Enable Set Register1 +380h,ECR0,System Event Enable Clear Register0 +384h,ECR1,System Event Enable Clear Register1 +400h,CMR0,Channel Map Register0 +404h,CMR1,Channel Map Register1 +408h,CMR2,Channel Map Register2 +40Ch,CMR3,Channel Map Register3 +410h,CMR4,Channel Map Register4 +414h,CMR5,Channel Map Register5 +418h,CMR6,Channel Map Register6 +41Ch,CMR7,Channel Map Register7 +420h,CMR8,Channel Map Register8 +424h,CMR9,Channel Map Register9 +428h,CMR10,Channel Map Register10 +42Ch,CMR11,Channel Map Register11 +430h,CMR12,Channel Map Register12 +434h,CMR13,Channel Map Register13 +438h,CMR14,Channel Map Register14 +43Ch,CMR15,Channel Map Register15 +800h,HMR0,Host Interrupt Map Register0 +804h,HMR1,Host Interrupt Map Register1 +808h,HMR2,Host Interrupt Map Register2 +900h,HIPIR0,Host Interrupt Prioritized Index Register0 +904h,HIPIR1,Host Interrupt Prioritized Index Register1 +908h,HIPIR2,Host Interrupt Prioritized Index Register2 +90Ch,HIPIR3,Host Interrupt Prioritized Index Register3 +910h,HIPIR4,Host Interrupt Prioritized Index Register4 +914h,HIPIR5,Host Interrupt Prioritized Index Register5 +918h,HIPIR6,Host Interrupt Prioritized Index Register6 +91Ch,HIPIR7,Host Interrupt Prioritized Index Register7 +920h,HIPIR8,Host Interrupt Prioritized Index Register8 +924h,HIPIR9,Host Interrupt Prioritized Index Register9 +D00h,SIPR0,System Event Polarity Register0 +D04h,SIPR1,System Event Polarity Register1 +D80h,SITR0,System Event Type Register0 +D84h,SITR1,System Event Type Register1 +1100h,HINLR0,Host Interrupt Nesting Level Register0 +1104h,HINLR1,Host Interrupt Nesting Level Register1 +1108h,HINLR2,Host Interrupt Nesting Level Register2 +110Ch,HINLR3,Host Interrupt Nesting Level Register3 +1110h,HINLR4,Host Interrupt Nesting Level Register4 +1114h,HINLR5,Host Interrupt Nesting Level Register5 +1118h,HINLR6,Host Interrupt Nesting Level Register6 +111Ch,HINLR7,Host Interrupt Nesting Level Register7 +1120h,HINLR8,Host Interrupt Nesting Level Register8 +1124h,HINLR9,Host Interrupt Nesting Level Register9 +1500h,HIER,Host Interrupt Enable Register diff --git a/arch/am335x/pwmss-ecap.csv b/arch/am335x/pwmss-ecap.csv new file mode 100644 index 0000000..ba684ca --- /dev/null +++ b/arch/am335x/pwmss-ecap.csv @@ -0,0 +1,14 @@ +Offset,Name,Description +0h,TSCTR,Time-Stamp Counter Register +4h,CTRPHS,Counter Phase Offset Value Register +8h,CAP1,Capture 1 Register +Ch,CAP2,Capture 2 Register +10h,CAP3,Capture 3 Register +14h,CAP4,Capture 4 Register +28h,ECCTL1,Capture Control Register 1 +2Ah,ECCTL2,Capture Control Register 2 +2Ch,ECEINT,Capture Interrupt Enable Register +2Eh,ECFLG,Capture Interrupt Flag Register +30h,ECCLR,Capture Interrupt Clear Register +32h,ECFRC,Capture Interrupt Force Register +5Ch,REVID,Revision ID Register diff --git a/arch/am335x/pwmss-epwm.csv b/arch/am335x/pwmss-epwm.csv new file mode 100644 index 0000000..c49b0c0 --- /dev/null +++ b/arch/am335x/pwmss-epwm.csv @@ -0,0 +1,31 @@ +Offset,Name,Description +0h,TBCTL,Time-Base Control Register +2h,TBSTS,Time-Base Status Register +4h,TBPHSHR,Extension for HRPWM Phase Register +6h,TBPHS,Time-Base Phase Register +8h,TBCNT,Time-Base Counter Register +Ah,TBPRD,Time-Base Period Register +Eh,CMPCTL,Counter-Compare Control Register +10h,CMPAHR,Extension for HRPWM Counter-Compare A Register +12h,CMPA,Counter-Compare A Register +14h,CMPB,Counter-Compare B Register +16h,AQCTLA,Action-Qualifier Control Register for Output A (EPWMxA) +18h,AQCTLB,Action-Qualifier Control Register for Output B (EPWMxB) +1Ah,AQSFRC,Action-Qualifier Software Force Register +1Ch,AQCSFRC,Action-Qualifier Continuous S/W Force Register Set +1Eh,DBCTL,Dead-Band Generator Control Register +20h,DBRED,Dead-Band Generator Rising Edge Delay Count Register +22h,DBFED,Dead-Band Generator Falling Edge Delay Count Register +24h,TZSEL,Trip-Zone Select Register +28h,TZCTL,Trip-Zone Control Register +2Ah,TZEINT,Trip-Zone Enable Interrupt Register +2Ch,TZFLG,Trip-Zone Flag Register +2Eh,TZCLR,Trip-Zone Clear Register +30h,TZFRC,Trip-Zone Force Register +32h,ETSEL,Event-Trigger Selection Register +34h,ETPS,Event-Trigger Pre-Scale Register +36h,ETFLG,Event-Trigger Flag Register +38h,ETCLR,Event-Trigger Clear Register +3Ah,ETFRC,Event-Trigger Force Register +3Ch,PCCTL,PWM-Chopper Control Register +C0h,HRCNFG,HRPWM configuration Register diff --git a/arch/am335x/pwmss.csv b/arch/am335x/pwmss.csv new file mode 100644 index 0000000..494f045 --- /dev/null +++ b/arch/am335x/pwmss.csv @@ -0,0 +1,5 @@ +Offset,Name,Description +0h,IDVER,IP Revision Register +4h,SYSCONFIG,System Configuration Register +8h,CLKCONFIG,Clock Configuration Register +Ch,CLKSTATUS,Clock Status Register diff --git a/arch/am335x/soc-ctrl.csv b/arch/am335x/soc-ctrl.csv new file mode 100644 index 0000000..b19c0ac --- /dev/null +++ b/arch/am335x/soc-ctrl.csv @@ -0,0 +1,215 @@ +Offset,Name,Description +0h,control_revision, +4h,control_hwinfo, +10h,control_sysconfig, +40h,control_status, +110h,control_emif_sdram_config, +428h,core_sldo_ctrl, +42Ch,mpu_sldo_ctrl, +444h,clk32kdivratio_ctrl, +448h,bandgap_ctrl, +44Ch,bandgap_trim, +458h,pll_clkinpulow_ctrl, +468h,mosc_ctrl, +470h,deepsleep_ctrl, +50Ch,dpll_pwr_sw_status, +600h,device_id, +604h,dev_feature, +608h,init_priority_0, +60Ch,init_priority_1, +614h,tptc_cfg, +620h,usb_ctrl0, +624h,usb_sts0, +628h,usb_ctrl1, +62Ch,usb_sts1, +630h,mac_id0_lo, +634h,mac_id0_hi, +638h,mac_id1_lo, +63Ch,mac_id1_hi, +644h,dcan_raminit, +648h,usb_wkup_ctrl, +650h,gmii_sel, +664h,pwmss_ctrl, +670h,mreqprio_0, +674h,mreqprio_1, +690h,hw_event_sel_grp1, +694h,hw_event_sel_grp2, +698h,hw_event_sel_grp3, +69Ch,hw_event_sel_grp4, +6A0h,smrt_ctrl, +6A4h,mpuss_hw_debug_sel, +6A8h,mpuss_hw_dbg_info, +770h,vdd_mpu_opp_050, +774h,vdd_mpu_opp_100, +778h,vdd_mpu_opp_120, +77Ch,vdd_mpu_opp_turbo, +7B8h,vdd_core_opp_050, +7BCh,vdd_core_opp_100, +7D0h,bb_scale, +7F4h,usb_vid_pid, +7FCh,efuse_sma, +800h,conf_gpmc_ad0, +804h,conf_gpmc_ad1, +808h,conf_gpmc_ad2, +80Ch,conf_gpmc_ad3, +810h,conf_gpmc_ad4, +814h,conf_gpmc_ad5, +818h,conf_gpmc_ad6, +81Ch,conf_gpmc_ad7, +820h,conf_gpmc_ad8, +824h,conf_gpmc_ad9, +828h,conf_gpmc_ad10, +82Ch,conf_gpmc_ad11, +830h,conf_gpmc_ad12, +834h,conf_gpmc_ad13, +838h,conf_gpmc_ad14, +83Ch,conf_gpmc_ad15, +840h,conf_gpmc_a0, +844h,conf_gpmc_a1, +848h,conf_gpmc_a2, +84Ch,conf_gpmc_a3, +850h,conf_gpmc_a4, +854h,conf_gpmc_a5, +858h,conf_gpmc_a6, +85Ch,conf_gpmc_a7, +860h,conf_gpmc_a8, +864h,conf_gpmc_a9, +868h,conf_gpmc_a10, +86Ch,conf_gpmc_a11, +870h,conf_gpmc_wait0, +874h,conf_gpmc_wpn, +878h,conf_gpmc_ben1, +87Ch,conf_gpmc_csn0, +880h,conf_gpmc_csn1, +884h,conf_gpmc_csn2, +888h,conf_gpmc_csn3, +88Ch,conf_gpmc_clk, +890h,conf_gpmc_advn_ale, +894h,conf_gpmc_oen_ren, +898h,conf_gpmc_wen, +89Ch,conf_gpmc_ben0_cle, +8A0h,conf_lcd_data0, +8A4h,conf_lcd_data1, +8A8h,conf_lcd_data2, +8ACh,conf_lcd_data3, +8B0h,conf_lcd_data4, +8B4h,conf_lcd_data5, +8B8h,conf_lcd_data6, +8BCh,conf_lcd_data7, +8C0h,conf_lcd_data8, +8C4h,conf_lcd_data9, +8C8h,conf_lcd_data10, +8CCh,conf_lcd_data11, +8D0h,conf_lcd_data12, +8D4h,conf_lcd_data13, +8D8h,conf_lcd_data14, +8DCh,conf_lcd_data15, +8E0h,conf_lcd_vsync, +8E4h,conf_lcd_hsync, +8E8h,conf_lcd_pclk, +8ECh,conf_lcd_ac_bias_en, +8F0h,conf_mmc0_dat3, +8F4h,conf_mmc0_dat2, +8F8h,conf_mmc0_dat1, +8FCh,conf_mmc0_dat0, +900h,conf_mmc0_clk, +904h,conf_mmc0_cmd, +908h,conf_mii1_col, +90Ch,conf_mii1_crs, +910h,conf_mii1_rx_er, +914h,conf_mii1_tx_en, +918h,conf_mii1_rx_dv, +91Ch,conf_mii1_txd3, +920h,conf_mii1_txd2, +924h,conf_mii1_txd1, +928h,conf_mii1_txd0, +92Ch,conf_mii1_tx_clk, +930h,conf_mii1_rx_clk, +934h,conf_mii1_rxd3, +938h,conf_mii1_rxd2, +93Ch,conf_mii1_rxd1, +940h,conf_mii1_rxd0, +944h,conf_rmii1_ref_clk, +948h,conf_mdio, +94Ch,conf_mdc, +950h,conf_spi0_sclk, +954h,conf_spi0_d0, +958h,conf_spi0_d1, +95Ch,conf_spi0_cs0, +960h,conf_spi0_cs1, +964h,conf_ecap0_in_pwm0_out, +968h,conf_uart0_ctsn, +96Ch,conf_uart0_rtsn, +970h,conf_uart0_rxd, +974h,conf_uart0_txd, +978h,conf_uart1_ctsn, +97Ch,conf_uart1_rtsn, +980h,conf_uart1_rxd, +984h,conf_uart1_txd, +988h,conf_i2c0_sda, +98Ch,conf_i2c0_scl, +990h,conf_mcasp0_aclkx, +994h,conf_mcasp0_fsx, +998h,conf_mcasp0_axr0, +99Ch,conf_mcasp0_ahclkr, +9A0h,conf_mcasp0_aclkr, +9A4h,conf_mcasp0_fsr, +9A8h,conf_mcasp0_axr1, +9ACh,conf_mcasp0_ahclkx, +9B0h,conf_xdma_event_intr0, +9B4h,conf_xdma_event_intr1, +9B8h,conf_warmrstn, +9C0h,conf_nnmi, +9D0h,conf_tms, +9D4h,conf_tdi, +9D8h,conf_tdo, +9DCh,conf_tck, +9E0h,conf_trstn, +9E4h,conf_emu0, +9E8h,conf_emu1, +9F8h,conf_rtc_pwronrstn, +9FCh,conf_pmic_power_en, +A00h,conf_ext_wakeup, +A1Ch,conf_usb0_drvvbus, +A34h,conf_usb1_drvvbus, +E00h,cqdetect_status, +E04h,ddr_io_ctrl, +E0Ch,vtp_ctrl, +E14h,vref_ctrl, +F90h,tpcc_evt_mux_0_3, +F94h,tpcc_evt_mux_4_7, +F98h,tpcc_evt_mux_8_11, +F9Ch,tpcc_evt_mux_12_15, +FA0h,tpcc_evt_mux_16_19, +FA4h,tpcc_evt_mux_20_23, +FA8h,tpcc_evt_mux_24_27, +FACh,tpcc_evt_mux_28_31, +FB0h,tpcc_evt_mux_32_35, +FB4h,tpcc_evt_mux_36_39, +FB8h,tpcc_evt_mux_40_43, +FBCh,tpcc_evt_mux_44_47, +FC0h,tpcc_evt_mux_48_51, +FC4h,tpcc_evt_mux_52_55, +FC8h,tpcc_evt_mux_56_59, +FCCh,tpcc_evt_mux_60_63, +FD0h,timer_evt_capt, +FD4h,ecap_evt_capt, +FD8h,adc_evt_capt, +1000h,reset_iso, +1318h,dpll_pwr_sw_ctrl, +131Ch,ddr_cke_ctrl, +1320h,sma2, +1324h,m3_txev_eoi, +1328h,ipc_msg_reg0, +132Ch,ipc_msg_reg1, +1330h,ipc_msg_reg2, +1334h,ipc_msg_reg3, +1338h,ipc_msg_reg4, +133Ch,ipc_msg_reg5, +1340h,ipc_msg_reg6, +1344h,ipc_msg_reg7, +1404h,ddr_cmd0_ioctrl, +1408h,ddr_cmd1_ioctrl, +140Ch,ddr_cmd2_ioctrl, +1440h,ddr_data0_ioctrl, +1444h,ddr_data1_ioctrl, diff --git a/examples/led_outin/README.md b/examples/led_outin/README.md deleted file mode 100644 index de7ff07..0000000 --- a/examples/led_outin/README.md +++ /dev/null @@ -1 +0,0 @@ -This example flashes a LED on pin P9_25 and reads the value on P9_23. diff --git a/examples/led_outin/led_outin.c b/examples/led_outin/led_outin.c deleted file mode 100644 index 18a6db7..0000000 --- a/examples/led_outin/led_outin.c +++ /dev/null @@ -1,73 +0,0 @@ -#include -#include -#include - -#include "lib/args/args.h" -#include "lib/coroutine/coroutine.h" -#include "lib/debug/debug.h" -#include "lib/gpio/gpio.h" -#include "lib/initproc/initproc.h" -#include "lib/intc/service.h" -#include "lib/log/daemon/daemon.h" -#include "lib/pinmap/pinmap.h" -#include "lib/resource/table.h" -#include "lib/rpmsg/rpmsg.h" -#include "lib/time/clock.h" -#include "lib/time/process.h" - -// Note: the argument is cycles / 5 because 5 ns cycle -#define PERIOD (2000000000U / 5) - -void toggle_blue(ThreadID tid, Args args) { - gpio_pin pin = GPIO_PIN(P9_23); - PRULOG_1u32(INFO, "starting blue half-cycle %uns", PERIOD); - - Timestamp clock; - ReadClock(&clock); - while (1) { - PRULOG_0(INFO, "on"); - - GPIO_SetPin(pin, 1); - SleepUntil(&clock, PERIOD); - - PRULOG_0(INFO_NOYIELD, "off"); - GPIO_SetPin(pin, 0); - SleepUntil(&clock, PERIOD); - } -} - -void read_yellow(ThreadID tid, Args args) { - gpio_pin pin = GPIO_PIN(P9_25); - - PRULOG_1u32(INFO, "starting yellow reader %uns", PERIOD / 2); - - Timestamp clock; - ReadClock(&clock); - while (1) { - uint32_t value = GPIO_GetPin(pin); - PRULOG_1u32(INFO_NOYIELD, "yellow is %u", value); - SleepUntil(&clock, PERIOD / 2); - } -} - -SUPRUGLUE_DEFINE_THREAD(blue, 256); -SUPRUGLUE_DEFINE_THREAD(yellow, 256); - -int main(void) { - Args args; - - Init(NewSystemConfig()); - InterruptServiceInit(); - ClockInit(); - RpmsgInit(&__transport, &resourceTable.rpmsg_vdev, &resourceTable.rpmsg_vring0, &resourceTable.rpmsg_vring1); - GPIO_Init(); - SyslogInit(); - ProcessInit(); - - args.ptr = "0"; - - Create(&blue.thread, toggle_blue, args, "blue", sizeof(blue.space)); - Create(&yellow.thread, read_yellow, args, "yellow", sizeof(yellow.space)); - - return Run(); -} diff --git a/examples/pwm_outin/BUILD b/examples/pwm_outin/BUILD index cc77b07..435e79c 100644 --- a/examples/pwm_outin/BUILD +++ b/examples/pwm_outin/BUILD @@ -14,14 +14,14 @@ cc_binary( ], deps = [ "//lib/coroutine", - "//lib/gpio", + "//lib/cap", "//lib/initproc", "//lib/intc:service", "//lib/log/daemon", - "//lib/rpmsg", "//lib/pwm", - "//lib/time:process", "//lib/resource", + "//lib/rpmsg", + "//lib/time:process", "//tools/toolchain/am335x", ], ) @@ -31,11 +31,12 @@ genrule( srcs = [ # Order is important: args[0] is all events # Remaining args define arriving system events. - # (Only) one should set the host. + # (Only) one should set the host interrupt number. "//arch:sysevts", "//lib/rpmsg/am335x:irq", "//lib/time/am335x:iep_tim_cap_cmp_pend", "//lib/pwm/am335x:epwm1_intr_pend", + "//lib/cap/am335x:pru_ecap_intr_pend", ], outs = [ "irq.c", diff --git a/examples/pwm_outin/pwm_outin.c b/examples/pwm_outin/pwm_outin.c index 642873c..844ab01 100644 --- a/examples/pwm_outin/pwm_outin.c +++ b/examples/pwm_outin/pwm_outin.c @@ -2,19 +2,20 @@ #include #include -#include "external/ti-pru-support/include/am335x/pru_intc.h" // @@@ +// @@@ TODO: here for diagnostics, remove! +#include "external/ti-pru-support/include/am335x/pru_ecap.h" +#include "external/ti-pru-support/include/am335x/pru_intc.h" #include "external/ti-pru-support/include/am335x/sys_pwmss.h" #include "lib/args/args.h" +#include "lib/cap/cap.h" #include "lib/coroutine/coroutine.h" #include "lib/debug/debug.h" -#include "lib/gpio/gpio.h" #include "lib/initproc/initproc.h" #include "lib/intc/intc.h" #include "lib/intc/service.h" #include "lib/log/daemon/daemon.h" #include "lib/log/journal/journal.h" -#include "lib/pinmap/pinmap.h" #include "lib/pwm/pwm.h" #include "lib/resource/table.h" #include "lib/rpmsg/rpmsg.h" @@ -24,41 +25,31 @@ #define PERIOD (2000000000U / 5) -void pwmHandler(void) { - gpio_pin pin = GPIO_PIN(P9_12); - uint32_t value = GPIO_GetPin(pin); - PRULOG_1u32(INFO, "interrupt EPWM1 output A", value); +void pwmHandler(Args args) { + uint32_t clk = PWMSS1.EPWM_TBCNT; + PRULOG_1u32(INFO, "interrupt EPWM1 output A %u", clk); PWM_ClearInterrupt(); } -void runBlue(ThreadID tid, Args args) { - gpio_pin pin = GPIO_PIN(P9_12); +void ecapHandler(Args args) { + uint32_t up = CT_ECAP.CAP1; + uint32_t down = CT_ECAP.CAP2; + PRULOG_2u32(INFO, "interrupt ECAP up %u down %u", up, down); + CAP_ClearInterrupt(); +} +void runBlue(ThreadID tid, Args args) { PRULOG_1u32(INFO, "starting reader %uns", PERIOD / 2); - PWM_ClearInterrupt(); Timestamp clock; ReadClock(&clock); while (1) { - uint32_t value = GPIO_GetPin(pin); - - // uint32_t val1 = PWMSS1.EPWM_TBCNT; - // uint32_t val2 = PWMSS1.EPWM_ETPS; - // uint32_t val2 = PWMSS1.EPWM_ETFLG; - // uint32_t val2 = PWMSS1.EPWM_ETSEL; - // uint32_t val2 = PWMSS1.EPWM_CMPB; - // uint32_t val2 = EDMA_BASE[SHADOW1(EDMAREG_SERH)]; - uint32_t val1 = EDMA_BASE[SHADOW1(EDMAREG_IER)]; - uint32_t val2 = EDMA_BASE[SHADOW1(EDMAREG_IERH)]; + uint32_t cap = CT_ECAP.TSCTR; + uint32_t pwm = PWMSS1.EPWM_TBCNT; - val1 = CT_INTC.ESR0; - val2 = CT_INTC.ESR1; + PRULOG_2u32(INFO_NOYIELD, "read clocks cap %u tbcnt %u", cap, pwm); - PRULOG_2u32(INFO_NOYIELD, "val1 %u val2 %u", val1, val2); - - PWM_ClearInterrupt(); - - SleepUntil(&clock, PERIOD / 2); + SleepUntil32(&clock, PERIOD / 2); } } @@ -68,23 +59,26 @@ int main(void) { Args args; Init(NewSystemConfig()); - PWM_Init(); + PWM_Init(5000, 10000, 7500); InterruptServiceInit(); ClockInit(); RpmsgInit(&__transport, &resourceTable.rpmsg_vdev, &resourceTable.rpmsg_vring0, &resourceTable.rpmsg_vring1); - GPIO_Init(); SyslogInit(); ProcessInit(); + CAP_Init(); - args.ptr = "0"; + args.ptr = "0"; // @@@ Create(&blue.thread, runBlue, args, "blue", sizeof(blue.space)); - InterruptHandlerInit(SYSEVT_EPWM1_INTR_PEND, pwmHandler); + InterruptHandlerInit(SYSEVT_TPCC_INT_PEND_PO1, pwmHandler, args); + InterruptHandlerInit(SYSEVT_PR1_PRU_ECAP_INTR_REQ, ecapHandler, args); - PWM_Enable(); + // @@@ TODO remove + PWM_ClearInterrupt(); - // @@@ TODO need to add this call in other tests, examples... + CAP_Enable(); + PWM_Enable(); ControllerEnable(); return Run(); diff --git a/examples/led_outin/BUILD b/examples/simple_timer/BUILD similarity index 95% rename from examples/led_outin/BUILD rename to examples/simple_timer/BUILD index 1338ffc..6cde545 100644 --- a/examples/led_outin/BUILD +++ b/examples/simple_timer/BUILD @@ -1,8 +1,8 @@ # -*- Mode: Python -*- cc_binary( - name = "led_outin", + name = "simple_timer", srcs = [ - "led_outin.c", + "simple_timer.c", ":irqgen", ], additional_linker_inputs = [ @@ -18,9 +18,9 @@ cc_binary( "//lib/initproc", "//lib/intc:service", "//lib/log/daemon", + "//lib/resource", "//lib/rpmsg", "//lib/time:process", - "//lib/resource", "//tools/toolchain/am335x", ], ) diff --git a/examples/simple_timer/README.md b/examples/simple_timer/README.md new file mode 100644 index 0000000..a5f254d --- /dev/null +++ b/examples/simple_timer/README.md @@ -0,0 +1 @@ +This example toggles P8_11 on and off with an externally-configurable duty cycle. diff --git a/examples/simple_timer/simple_timer.c b/examples/simple_timer/simple_timer.c new file mode 100644 index 0000000..a52c69e --- /dev/null +++ b/examples/simple_timer/simple_timer.c @@ -0,0 +1,75 @@ +#include +#include +#include + +#include "lib/args/args.h" +#include "lib/coroutine/coroutine.h" +#include "lib/debug/debug.h" +#include "lib/gpio/gpio.h" +#include "lib/initproc/initproc.h" +#include "lib/intc/service.h" +#include "lib/log/daemon/daemon.h" +#include "lib/pinmap/pinmap.h" +#include "lib/resource/table.h" +#include "lib/rpmsg/rpmsg.h" +#include "lib/time/clock.h" +#include "lib/time/process.h" + +#define SECOND 200000000 + +// TODO: Configure these from the environment. +#define DUTY 12 +#define CYCLE 24 +#define PERIOD (2 * 3600) + +#define ON_FOR ((DUTY * PERIOD) / CYCLE) +#define OFF_FOR (((CYCLE - DUTY) * PERIOD) / CYCLE) + +void toggle_timer(ThreadID tid, Args args) { + gpio_pin pinO = GPIO_PIN(P8_11); + + Timestamp clock; + ReadClock(&clock); + + uint64_t oncycles = SECOND; + oncycles *= ON_FOR; + + uint64_t offcycles = SECOND; + offcycles *= OFF_FOR; + + while (1) { + PRULOG_1u64(INFO, "simple timer on %us", ON_FOR); + + GPIO_SetPin(pinO, 1); + + SleepUntil64(&clock, oncycles); + + PRULOG_1u64(INFO, "simple timer off %us", OFF_FOR); + + GPIO_SetPin(pinO, 0); + + SleepUntil64(&clock, offcycles); + } +} + +SUPRUGLUE_DEFINE_THREAD(timer, 256); + +int main(void) { + Args args; + + Init(NewSystemConfig()); + InterruptServiceInit(); + ClockInit(); + RpmsgInit(&__transport, &resourceTable.rpmsg_vdev, &resourceTable.rpmsg_vring0, &resourceTable.rpmsg_vring1); + GPIO_Init(); + SyslogInit(); + ProcessInit(); + + args.ptr = "0"; + + Create(&timer.thread, toggle_timer, args, "timer", sizeof(timer.space)); + + ControllerEnable(); + + return Run(); +} diff --git a/examples/two_leds/BUILD b/examples/two_leds/BUILD index 2080298..acf31b4 100644 --- a/examples/two_leds/BUILD +++ b/examples/two_leds/BUILD @@ -18,9 +18,9 @@ cc_binary( "//lib/initproc", "//lib/intc:service", "//lib/log/daemon", + "//lib/resource", "//lib/rpmsg", "//lib/time:process", - "//lib/resource", "//tools/toolchain/am335x", ], ) diff --git a/examples/ui1203/BUILD b/examples/ui1203/BUILD new file mode 100644 index 0000000..6bfe61e --- /dev/null +++ b/examples/ui1203/BUILD @@ -0,0 +1,48 @@ +# -*- Mode: Python -*- +cc_binary( + name = "ui1203", + srcs = [ + "ui1203.c", + ":irqgen", + ], + additional_linker_inputs = [ + "//tools/toolchain/am335x:linker_cmd", + ], + linkopts = [ + "$(location //tools/toolchain/am335x:linker_cmd)", + "--stack_size=0xe00", + ], + deps = [ + "//lib/coroutine", + "//lib/gpio", + "//lib/initproc", + "//lib/intc:service", + "//lib/log/daemon", + "//lib/resource", + "//lib/rpmsg", + "//lib/time:process", + "//lib/ui1203", + "//tools/toolchain/am335x", + ], +) + +genrule( + name = "irqgen", + srcs = [ + # Order is important: args[0] is all events + # Remaining args define arriving system events. + # (Only) one should set the host interrupt number. + "//arch:sysevts", + "//lib/rpmsg/am335x:irq", + "//lib/time/am335x:iep_tim_cap_cmp_pend", + "//lib/pwm/am335x:epwm1_intr_pend", + "//lib/cap/am335x:pru_ecap_intr_pend", + ], + outs = [ + "irq.c", + ], + cmd = "./$(location //tools/cmd/irqgen:irqgen) $(SRCS) > $@", + tools = [ + "//tools/cmd/irqgen", + ], +) diff --git a/examples/ui1203/ui1203.c b/examples/ui1203/ui1203.c new file mode 100644 index 0000000..da6e915 --- /dev/null +++ b/examples/ui1203/ui1203.c @@ -0,0 +1,71 @@ +#include +#include +#include + +#include "lib/args/args.h" +#include "lib/cap/cap.h" +#include "lib/coroutine/coroutine.h" +#include "lib/debug/debug.h" +#include "lib/gpio/gpio.h" +#include "lib/initproc/initproc.h" +#include "lib/intc/intc.h" +#include "lib/intc/service.h" +#include "lib/log/daemon/daemon.h" +#include "lib/log/journal/journal.h" +#include "lib/pinmap/pinmap.h" +#include "lib/pwm/pwm.h" +#include "lib/resource/table.h" +#include "lib/rpmsg/rpmsg.h" +#include "lib/soc/sysevts.h" +#include "lib/time/clock.h" +#include "lib/time/process.h" +#include "lib/ui1203/ui1203.h" + +#define PERIOD (2000000000U / 5) + +UI1203_Reader reader; +UI1203_Writer writer; + +void runBlue(ThreadID tid, Args args) { + + Timestamp clock; + ReadClock(&clock); + while (1) { + PRULOG_0(INFO_NOYIELD, "blue"); + + SleepUntil32(&clock, PERIOD); + } +} + +SUPRUGLUE_DEFINE_THREAD(blue, 256); + +int main(void) { + Init(NewSystemConfig()); + + PWM_Init(5000, 10000, 2500); + CAP_Init(); + + InterruptServiceInit(); + ClockInit(); + RpmsgInit(&__transport, &resourceTable.rpmsg_vdev, &resourceTable.rpmsg_vring0, &resourceTable.rpmsg_vring1); + GPIO_Init(); + SyslogInit(); + ProcessInit(); + + UI1203_Init_Reader(&reader, GPIO_PIN(P9_25)); + UI1203_Init_Writer(&writer, GPIO_PIN(P9_23)); + + Args args; + args.ptr = "0"; // @@@ + Create(&blue.thread, runBlue, args, "blue", sizeof(blue.space)); + + PWM_ClearInterrupt(); + PWM_Enable(); + + CAP_ClearInterrupt(); + CAP_Enable(); + + ControllerEnable(); + + return Run(); +} diff --git a/kernel/KERNEL.diff b/kernel/KERNEL.diff new file mode 100644 index 0000000..a6765fa --- /dev/null +++ b/kernel/KERNEL.diff @@ -0,0 +1,179 @@ +diff --git a/arch/arm/boot/dts/am335x-bone-common-univ.dtsi b/arch/arm/boot/dts/am335x-bone-common-univ.dtsi +index 72b9d85e1d6f..813fa695b69a 100644 +--- a/arch/arm/boot/dts/am335x-bone-common-univ.dtsi ++++ b/arch/arm/boot/dts/am335x-bone-common-univ.dtsi +@@ -73,7 +73,7 @@ BONE_PIN(P8_10, gpio_pd, P8_10(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) + BONE_PIN(P8_10, timer, P8_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) + + /* P8_11 (ZCZ ball R12) gpmc_ad13 (gpio1_13) */ +- BONE_PIN(P8_11, default, P8_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_11, default, P8_11(PIN_OUTPUT | MUX_MODE7)) + BONE_PIN(P8_11, gpio, P8_11(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) + BONE_PIN(P8_11, gpio_pu, P8_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) + BONE_PIN(P8_11, gpio_pd, P8_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) +@@ -81,7 +81,7 @@ BONE_PIN(P8_11, eqep, P8_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) + BONE_PIN(P8_11, pruout, P8_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6)) + + /* P8_12 (ZCZ ball T12) gpmc_ad12 (gpio1_12) */ +- BONE_PIN(P8_12, default, P8_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_12, default, P8_12(PIN_OUTPUT | MUX_MODE7)) + BONE_PIN(P8_12, gpio, P8_12(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) + BONE_PIN(P8_12, gpio_pu, P8_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) + BONE_PIN(P8_12, gpio_pd, P8_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) +@@ -393,7 +393,7 @@ BONE_PIN(P9_13, gpio_pd, P9_13(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) + BONE_PIN(P9_13, uart, P9_13(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6)) + + /* P9_14 (ZCZ ball U14) gpmc_a2 (gpio1_18) */ +- BONE_PIN(P9_14, default, P9_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_14, default, P9_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6)) + BONE_PIN(P9_14, gpio, P9_14(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) + BONE_PIN(P9_14, gpio_pu, P9_14(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) + BONE_PIN(P9_14, gpio_pd, P9_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) +@@ -478,7 +478,7 @@ BONE_PIN(P9_22, pwm, P9_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) + BONE_PIN(P9_22, pru_uart, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) + + /* P9_23 (ZCZ ball V14) gpmc_a1 (gpio1_17) */ +- BONE_PIN(P9_23, default, P9_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_23, default, P9_23(PIN_OUTPUT | MUX_MODE7)) + BONE_PIN(P9_23, gpio, P9_23(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) + BONE_PIN(P9_23, gpio_pu, P9_23(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) + BONE_PIN(P9_23, gpio_pd, P9_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) +@@ -602,7 +602,7 @@ BONE_PIN(P9_91, pruout, P9_91(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) + BONE_PIN(P9_91, pruin, P9_91(PIN_INPUT | MUX_MODE6)) + + /* P9_42 (ZCZ ball C18) eCAP0_in_PWM0_out (gpio0_7) */ +- BONE_PIN(P9_42, default, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_42, default, P9_42(PIN_INPUT | MUX_MODE3)) + BONE_PIN(P9_42, gpio, P9_42(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) + BONE_PIN(P9_42, gpio_pu, P9_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) + BONE_PIN(P9_42, gpio_pd, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) +@@ -614,7 +614,7 @@ BONE_PIN(P9_42, spi_sclk, P9_42(PIN_INPUT_PULLUP | MUX_MODE4)) + + /* P9_42.1 */ + /* P9_92 (ZCZ ball B12) mcasp0_aclkr (gpio3_18) */ +- BONE_PIN(P9_92, default, P9_92(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_92, default, P9_92(PIN_INPUT | MUX_MODE6)) + BONE_PIN(P9_92, gpio, P9_92(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) + BONE_PIN(P9_92, gpio_pu, P9_92(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) + BONE_PIN(P9_92, gpio_pd, P9_92(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) +@@ -1862,14 +1862,14 @@ P8_10 { + P8_11 { + gpio-name = "P8_11"; + gpio = <&gpio1 13 0>; +- input; ++ output; + dir-changeable; + }; + + P8_12 { + gpio-name = "P8_12"; + gpio = <&gpio1 12 0>; +- input; ++ output; + dir-changeable; + }; + +@@ -2198,7 +2198,7 @@ P9_22 { + P9_23 { + gpio-name = "P9_23"; + gpio = <&gpio1 17 0>; +- input; ++ output; + dir-changeable; + }; + +diff --git a/arch/arm/boot/dts/am33xx-clocks.dtsi b/arch/arm/boot/dts/am33xx-clocks.dtsi +index dced92a8970e..3d37b1051d52 100644 +--- a/arch/arm/boot/dts/am33xx-clocks.dtsi ++++ b/arch/arm/boot/dts/am33xx-clocks.dtsi +@@ -99,6 +99,7 @@ ehrpwm0_tbclk: ehrpwm0_tbclk@44e10664 { + clocks = <&l4ls_gclk>; + ti,bit-shift = <0>; + reg = <0x0664>; ++ ti,set-bit-to-disable; + }; + + ehrpwm1_tbclk: ehrpwm1_tbclk@44e10664 { +@@ -107,6 +108,7 @@ ehrpwm1_tbclk: ehrpwm1_tbclk@44e10664 { + clocks = <&l4ls_gclk>; + ti,bit-shift = <1>; + reg = <0x0664>; ++ ti,set-bit-to-disable; + }; + + ehrpwm2_tbclk: ehrpwm2_tbclk@44e10664 { +@@ -115,6 +117,7 @@ ehrpwm2_tbclk: ehrpwm2_tbclk@44e10664 { + clocks = <&l4ls_gclk>; + ti,bit-shift = <2>; + reg = <0x0664>; ++ ti,set-bit-to-disable; + }; + }; + &prcm_clocks { +diff --git a/arch/arm/boot/dts/am33xx-l4.dtsi b/arch/arm/boot/dts/am33xx-l4.dtsi +index ee95d6b70556..2e5c883b64fa 100644 +--- a/arch/arm/boot/dts/am33xx-l4.dtsi ++++ b/arch/arm/boot/dts/am33xx-l4.dtsi +@@ -848,6 +848,9 @@ pruss: pruss@0 { + #address-cells = <1>; + #size-cells = <1>; + ranges; ++ /* 0 and 1 are fixed for PRU-initiated DMAs, see TRM ... */ ++ dmas = <&edma 0 2>, <&edma 1 2>; ++ dma-names = "prucpy0", "prucpy1"; + + pruss_mem: memories@0 { + reg = <0x0 0x2000>, +@@ -904,13 +907,13 @@ pruss_mii_rt: mii-rt@32000 { + pruss_intc: interrupt-controller@20000 { + compatible = "ti,pruss-intc"; + reg = <0x20000 0x2000>; +- interrupts = <20>, <21>, <22>, <23>, <24>, <25>, <26>, <27>; ++ interrupts = <20>, <21>, <22>, <23>, <24>, <25>; + interrupt-names = "host_intr0", "host_intr1", + "host_intr2", "host_intr3", +- "host_intr4", "host_intr5", +- "host_intr6", "host_intr7"; ++ "host_intr4", "host_intr5"; + interrupt-controller; + #interrupt-cells = <3>; ++ ti,irqs-reserved = /bits/ 8 <0xC0>; /* BIT(7,8) */ + }; + + pru0: pru@34000 { +@@ -2067,6 +2070,7 @@ epwmss0: epwmss@0 { + #size-cells = <1>; + status = "disabled"; + ranges = <0 0 0x1000>; ++ ti,no-idle; + + ecap0: pwm@100 { + compatible = "ti,am3352-ecap"; +@@ -2124,6 +2128,7 @@ epwmss1: epwmss@0 { + #size-cells = <1>; + status = "disabled"; + ranges = <0 0 0x1000>; ++ ti,no-idle; + + ecap1: pwm@100 { + compatible = "ti,am3352-ecap"; +@@ -2181,6 +2186,7 @@ epwmss2: epwmss@0 { + #size-cells = <1>; + status = "disabled"; + ranges = <0 0 0x1000>; ++ ti,no-idle; + + ecap2: pwm@100 { + compatible = "ti,am3352-ecap"; +diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi +index 92fe2b900aa1..1aa182464aeb 100644 +--- a/arch/arm/boot/dts/am33xx.dtsi ++++ b/arch/arm/boot/dts/am33xx.dtsi +@@ -239,6 +239,7 @@ edma: dma@0 { + <&edma_tptc2 0>; + + ti,edma-memcpy-channels = <20 21>; ++ ti,edma-reserved-slot-ranges = <0 2>, <14 2>, <38 2>, <62 2>; + }; + }; + diff --git a/kernel/README.md b/kernel/README.md new file mode 100644 index 0000000..297cfe6 --- /dev/null +++ b/kernel/README.md @@ -0,0 +1,41 @@ +This directory includes Docker support for building Beaglbone Black kernels. + +https://github.com/RobertCNelson/ti-linux-kernel-dev + +## Build a docker image + +``` +(cd ./docker && make) +``` + +## Build a kernel .deb + +``` +./make.sh build +``` + +## (Re-)build a kernel .deb + +``` +./make.sh rebuild +``` + +## TODO + +Need to edit `system.sh` with: + +``` +AUTO_BUILD=1 +``` + +This prevents running `make menuconfig` and clobbering your config. +?? + +### Also note + +Required for the examples. + +``` +enable_uboot_overlays=1 +enable_uboot_cape_universal=1 +``` diff --git a/kernel/build.sh b/kernel/build.sh deleted file mode 100755 index a520119..0000000 --- a/kernel/build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -docker build -t supruglue docker diff --git a/kernel/compile.sh b/kernel/compile.sh deleted file mode 100755 index 9c8c534..0000000 --- a/kernel/compile.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -e - -cd /supruglue/kernel/ti-linux-kernel-dev - -echo Running build_deb.sh in `pwd` - -#./build_kernel.sh -#./build_deb.sh -./tools/rebuild_deb.sh - -echo Exited: build_deb.sh: $? diff --git a/kernel/docker/Makefile b/kernel/docker/Makefile new file mode 100644 index 0000000..bf99d52 --- /dev/null +++ b/kernel/docker/Makefile @@ -0,0 +1,2 @@ +docker: + docker build -t supruglue docker diff --git a/kernel/docker/run.sh b/kernel/docker/run.sh new file mode 100755 index 0000000..bac260b --- /dev/null +++ b/kernel/docker/run.sh @@ -0,0 +1,10 @@ +#!/bin/bash -e + +cd /supruglue/kernel/ti-linux-kernel-dev + +echo Running $1 in `pwd` + +# the command is passed in as $1 +$1 + +echo Exited: $? diff --git a/kernel/docker/shell.sh b/kernel/docker/shell.sh new file mode 100755 index 0000000..5942f3c --- /dev/null +++ b/kernel/docker/shell.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +docker run \ + -v ${HOME}/src/supruglue:/supruglue \ + -ti \ + supruglue \ + bash diff --git a/kernel/make.sh b/kernel/make.sh new file mode 100755 index 0000000..4902c15 --- /dev/null +++ b/kernel/make.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +SCRIPT= + +case ${1-rebuild} in + build) + SCRIPT=./build_deb.sh + ;; + rebuild) + SCRIPT=./tools/rebuild_deb.sh + ;; + *) + echo "usage: $0 [build|rebuild]" + exit 1 + ;; +esac + +docker run \ + -v ${HOME}/src/supruglue:/supruglue \ + -ti \ + supruglue \ + /supruglue/kernel/docker/run.sh ${SCRIPT} diff --git a/kernel/run.sh b/kernel/run.sh deleted file mode 100755 index 6c94f78..0000000 --- a/kernel/run.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -docker run \ - -v ${HOME}/src/supruglue:/supruglue \ - -ti \ - supruglue \ - /supruglue/kernel/compile.sh - - -# docker run \ ✔ 21:10:34 -# -v ${HOME}/src/supruglue/kernel:/supruglue \ -# -ti \ -# supruglue \ -# bash - diff --git a/kernel/system.sh b/kernel/system.sh deleted file mode 100644 index b47c8bc..0000000 --- a/kernel/system.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh -#copy as "system.sh" and tweak for your system - -ARCH=$(uname -m) - -#ARM Native gcc compiler (running gcc on arm target) -if [ "x${ARCH}" = "xarmv7l" ] || [ "x${ARCH}" = "xaarch64" ] ; then - #Native arm gcc compiler - CC= -fi - -###REQUIRED: - -#ARM GCC CROSS Compiler: -#if CC is not set, a known working linaro based gcc compiler will be downloaded and utilized. -#CC=/bin/arm-none-eabi- -#CC=/bin/arm-linux-gnueabi- -CC=/usr/bin/arm-linux-gnueabihf- - -###OPTIONAL: - -###OPTIONAL: CORES: number of CPU cores to use for compilation -#CORES=4 - -###OPTIONAL: LINUX_GIT: specify location of locally cloned git tree. -# -#LINUX_GIT=/supruglue/kernel/linux/ - -###OPTIONAL: MMC: (REQUIRED FOR RUNNING: tools/install_kernel.sh) -#Note: This operates on raw disks, NOT PARTITIONS.. -# -#WRONG: MMC=/dev/mmcblk0p1 -#CORRECT: MMC=/dev/mmcblk0 -# -#WRONG: MMC=/dev/sde1 -#CORRECT: MMC=/dev/sde -# -#MMC=/dev/sde - -###ADVANCED: RUN_BISECT: used with ./scripts/bisect.sh -# -#RUN_BISECT=1 - -###ADVANCED: AUTO_BUILD: Easier integration with Jenkins/Buildbot/etc.. -# -#AUTO_BUILD=1 diff --git a/kernel/ti-linux-kernel-dev b/kernel/ti-linux-kernel-dev index c68b848..86aa87f 160000 --- a/kernel/ti-linux-kernel-dev +++ b/kernel/ti-linux-kernel-dev @@ -1 +1 @@ -Subproject commit c68b848f0d2f702ba8e91a87efaa678b80c7101d +Subproject commit 86aa87f42f724e9cd36d863049272466a1925019 diff --git a/lib/cap/BUILD b/lib/cap/BUILD new file mode 100644 index 0000000..64c518e --- /dev/null +++ b/lib/cap/BUILD @@ -0,0 +1,25 @@ +# -*- Mode: Python -*- +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "defs", + hdrs = [ + "cap-defs.h", + ], + deps = [ + "//lib/pinmap", + ], +) + +cc_library( + name = "cap", + hdrs = [ + "cap.h", + ], + deps = [ + ":defs", + ] + select({ + "//tools/toolchain:am335x": ["//lib/cap/am335x"], + "//conditions:default": ["//lib/cap/test32"], + }), +) diff --git a/lib/cap/am335x/BUILD b/lib/cap/am335x/BUILD new file mode 100644 index 0000000..260d90b --- /dev/null +++ b/lib/cap/am335x/BUILD @@ -0,0 +1,24 @@ +# -*- Mode: Python -*- +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "am335x", + srcs = [ + "cap-am335x.c", + ], + hdrs = [ + "cap-am335x.h", + ], + deps = [ + "//lib/cap:defs", + "//tools/toolchain/am335x", + ], +) + +filegroup( + name = "pru_ecap_intr_pend", + srcs = [ + "pru_ecap_intr_pend.yaml", + ], +) + diff --git a/lib/cap/am335x/cap-am335x.c b/lib/cap/am335x/cap-am335x.c new file mode 100644 index 0000000..c12e4c4 --- /dev/null +++ b/lib/cap/am335x/cap-am335x.c @@ -0,0 +1,42 @@ +// Copyright Joshua MacDonald +// SPDX-License-Identifier: MIT + +#include "cap-am335x.h" +#include "external/ti-pru-support/include/am335x/pru_ecap.h" + +void CAP_Init(void) { + CT_ECAP.ECCLR = 0xFF; + + CT_ECAP.ECCTL1 = (3 << 14) | // Free run + (1 << 8) | // Capture enable + (0 << 7) | // Reset after 4 + (0 << 6) | // Cap4 polarity falling + (0 << 5) | // Reset after 3 + (0 << 4) | // Cap3 polarity rising + (1 << 3) | // Reset after 2 + (1 << 2) | // Cap2 polarity falling + (1 << 1) | // Reset after 1 + (0 << 0); // Cap1 polarity rising + + CT_ECAP.ECCTL2 = (0 << 9) | // Capture mode + (0 << 6) | // Sync out disable + (0 << 5) | // Sync in disable + (0 << 4) | // Stopped + (1 << 1) | // Capture 2 events + (0 << 0); // Continuous + + CT_ECAP.ECEINT = (1 << 2); // Interrupt on Cap2 + + CT_ECAP.ECCLR = CT_ECAP.ECFLG & 0xfe; // Clear flags +} + +void CAP_Enable(void) { + CT_ECAP.ECCTL2 |= (1 << 4); // Run +} + +void CAP_ClearInterrupt(void) { + CT_ECAP.ECCLR = (1 << 0) | // INTR + (1 << 1) | // CEVT1 + (1 << 2) | // CEVT2 + (1 << 5); // OFLOW +} diff --git a/lib/cap/am335x/cap-am335x.h b/lib/cap/am335x/cap-am335x.h new file mode 100644 index 0000000..f4de9e4 --- /dev/null +++ b/lib/cap/am335x/cap-am335x.h @@ -0,0 +1,17 @@ +// Copyright Joshua MacDonald +// SPDX-License-Identifier: MIT + +#include "lib/cap/cap-defs.h" + +#ifndef LIB_CAP_AM335X_CAP_H +#define LIB_CAP_AM335X_CAP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif // LIB_CAP_AM335X_CAP_H diff --git a/lib/cap/am335x/pru_ecap_intr_pend.yaml b/lib/cap/am335x/pru_ecap_intr_pend.yaml new file mode 100644 index 0000000..7e4a02d --- /dev/null +++ b/lib/cap/am335x/pru_ecap_intr_pend.yaml @@ -0,0 +1,4 @@ +incoming: +- event: SYSEVT_PR1_PRU_ECAP_INTR_REQ + channel: 6 + desc: PRU eCAP diff --git a/lib/cap/cap-defs.h b/lib/cap/cap-defs.h new file mode 100644 index 0000000..48d8b03 --- /dev/null +++ b/lib/cap/cap-defs.h @@ -0,0 +1,21 @@ +// Copyright Joshua MacDonald +// SPDX-License-Identifier: MIT + +#ifndef LIB_CAP_CAP_DEFS_H +#define LIB_CAP_CAP_DEFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lib/soc/soc.h" + +void CAP_Init(void); +void CAP_Enable(void); +void CAP_ClearInterrupt(void); + +#ifdef __cplusplus +} +#endif + +#endif // LIB_CAP_CAP_DEFS_H diff --git a/lib/cap/cap.h b/lib/cap/cap.h new file mode 100644 index 0000000..f71d030 --- /dev/null +++ b/lib/cap/cap.h @@ -0,0 +1,27 @@ +// Copyright Joshua MacDonald +// SPDX-License-Identifier: MIT + +#ifndef LIB_CAP_CAP_H +#define LIB_CAP_CAP_H + +#include "lib/pinmap/pinmap.h" +#include "lib/soc/soc.h" +#include + +#include "lib/cap/cap-defs.h" + +#if defined(SUPRUGLUE_AM335X) +#include "lib/cap/am335x/cap-am335x.h" +#elif defined(SUPRUGLUE_TEST32) +#include "lib/cap/test32/cap-test32.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif // LIB_GPIO_GPIO_H diff --git a/lib/cap/test32/BUILD b/lib/cap/test32/BUILD new file mode 100644 index 0000000..e8c22d5 --- /dev/null +++ b/lib/cap/test32/BUILD @@ -0,0 +1,24 @@ +# -*- Mode: Python -*- +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "test32", + srcs = [ + "cap-test32.cc", + ], + hdrs = [ + "cap-test32.h", + ], + deps = [ + "//lib/cap:defs", + ], +) + +cc_test( + name = "test", + srcs = ["cap_test.cc"], + deps = [ + "//lib/cap", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/lib/cap/test32/cap-test32.cc b/lib/cap/test32/cap-test32.cc new file mode 100644 index 0000000..af35d75 --- /dev/null +++ b/lib/cap/test32/cap-test32.cc @@ -0,0 +1,9 @@ +// Copyright Joshua MacDonald +// SPDX-License-Identifier: MIT + +#include + +#include "cap-test32.h" + +void CAP_Init(void) { +} diff --git a/lib/cap/test32/cap-test32.h b/lib/cap/test32/cap-test32.h new file mode 100644 index 0000000..41b9f1b --- /dev/null +++ b/lib/cap/test32/cap-test32.h @@ -0,0 +1,20 @@ +// Copyright Joshua MacDonald +// SPDX-License-Identifier: MIT + +#ifndef LIB_CAP_TEST32_CAP_H +#define LIB_CAP_TEST32_CAP_H + +#include + +#include "lib/cap/cap-defs.h" +#include "lib/soc/soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif // LIB_CAP_TEST32_CAP_H diff --git a/lib/cap/test32/cap_test.cc b/lib/cap/test32/cap_test.cc new file mode 100644 index 0000000..ad6db2c --- /dev/null +++ b/lib/cap/test32/cap_test.cc @@ -0,0 +1,13 @@ +#include "lib/cap/cap.h" +#include "lib/pinmap/pinmap.h" +#include "lib/soc/soc.h" +#include "gtest/gtest.h" + +class CapTest : public testing::Test { +protected: + void SetUp() override { + } +}; + +TEST_F(CapTest, Basic) { +} diff --git a/lib/coroutine/coroutine.c b/lib/coroutine/coroutine.c index 81c0b21..6d18de8 100755 --- a/lib/coroutine/coroutine.c +++ b/lib/coroutine/coroutine.c @@ -14,7 +14,7 @@ System __system; SystemConfig NewSystemConfig(void) { return (SystemConfig){ - .export_interval = 10 * TIME_SECOND, + .export_interval = 60 * 60 * TIME_SECOND64, }; } diff --git a/lib/coroutine/coroutine.h b/lib/coroutine/coroutine.h index bff4353..64fce61 100755 --- a/lib/coroutine/coroutine.h +++ b/lib/coroutine/coroutine.h @@ -21,7 +21,7 @@ typedef struct _System System; typedef struct _SystemConfig SystemConfig; struct _SystemConfig { - int32_t export_interval; + int64_t export_interval; }; struct _System { diff --git a/lib/dma/BUILD b/lib/dma/BUILD new file mode 100644 index 0000000..e7e3cb5 --- /dev/null +++ b/lib/dma/BUILD @@ -0,0 +1,25 @@ +# -*- Mode: Python -*- +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "defs", + hdrs = [ + "dma-defs.h", + ], + deps = [ + "//lib/pinmap", + ], +) + +cc_library( + name = "dma", + hdrs = [ + "dma.h", + ], + deps = [ + ":defs", + ] + select({ + "//tools/toolchain:am335x": ["//lib/dma/am335x"], + "//conditions:default": ["//lib/dma/test32"], + }), +) diff --git a/lib/dma/am335x/BUILD b/lib/dma/am335x/BUILD new file mode 100644 index 0000000..ddd77d8 --- /dev/null +++ b/lib/dma/am335x/BUILD @@ -0,0 +1,16 @@ +# -*- Mode: Python -*- +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "am335x", + srcs = [ + "dma-am335x.c", + ], + hdrs = [ + "dma-am335x.h", + ], + deps = [ + "//lib/dma:defs", + "//tools/toolchain/am335x", + ], +) diff --git a/lib/dma/am335x/dma-am335x.c b/lib/dma/am335x/dma-am335x.c new file mode 100644 index 0000000..fa51123 --- /dev/null +++ b/lib/dma/am335x/dma-am335x.c @@ -0,0 +1,7 @@ +// Copyright Joshua MacDonald +// SPDX-License-Identifier: MIT + +#include "dma-am335x.h" + +void DMA_Init(void) { +} diff --git a/lib/dma/am335x/dma-am335x.h b/lib/dma/am335x/dma-am335x.h new file mode 100644 index 0000000..2eaaf25 --- /dev/null +++ b/lib/dma/am335x/dma-am335x.h @@ -0,0 +1,138 @@ +// Copyright Joshua MacDonald +// SPDX-License-Identifier: MIT + +#ifndef LIB_DMA_AM335X_DMA_H +#define LIB_DMA_AM335X_DMA_H + +#include "lib/dma/dma-defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define EDMA_BASE ((volatile uint32_t *)(0x49000000)) +#define EDMA_DRAE1 (0x348 / WORDSZ) // DMA Region Access Enable Register for Region 1 Section 11.4.1.20 +#define EDMA_DRAEH1 (0x34C / WORDSZ) // DMA Region Access Enable Register High for Region 1 Section 11.4.1.21 + +#define EDMA_EMR (0x300 / WORDSZ) // Event Missed Register Section 11.4.1.9 +#define EDMA_EMRH (0x304 / WORDSZ) // Event Missed Register High Section 11.4.1.10 +#define EDMA_EMCR (0x308 / WORDSZ) // Event Missed Clear Register Section 11.4.1.11 +#define EDMA_EMCRH (0x30C / WORDSZ) // Event Missed Clear Register High Section 11.4.1.12 + +#define EDMA_CCERR (0x318 / WORDSZ) // EDMA3CC Error Register Section 11.4.1.15 +#define EDMA_EEVAL (0x320 / WORDSZ) // EDMA3CC EEVAL +#define EDMA_CCERRCLR (0x31C / WORDSZ) // EDMA3CC Error Clear Register Section 11.4.1.16 + +#define EDMAREG_ER 0x00 // Event Register Section 11.4.1.91 +#define EDMAREG_ERH 0x04 // Event Register High Section 11.4.1.92 +#define EDMAREG_ECR 0x08 // Event Clear Register Section 11.4.1.93 +#define EDMAREG_ECRH 0x0C // Event Clear Register High Section 11.4.1.94 +#define EDMAREG_ESR 0x10 // Event Set Register Section 11.4.1.95 +#define EDMAREG_ESRH 0x14 // Event Set Register High Section 11.4.1.96 +#define EDMAREG_CER 0x18 // Chained Event Register Section 11.4.1.97 +#define EDMAREG_CERH 0x1C // Chained Event Register High Section 11.4.1.98 +#define EDMAREG_EER 0x20 // Event Enable Register Section 11.4.1.99 +#define EDMAREG_EERH 0x24 // Event Enable Register High Section 11.4.1.100 +#define EDMAREG_EECR 0x28 // Event Enable Clear Register Section 11.4.1.101 +#define EDMAREG_EECRH 0x2C // Event Enable Clear Register High Section 11.4.1.102 +#define EDMAREG_EESR 0x30 // Event Enable Set Register Section 11.4.1.103 +#define EDMAREG_EESRH 0x34 // Event Enable Set Register High Section 11.4.1.104 +#define EDMAREG_SER 0x38 // Secondary Event Register Section 11.4.1.105 +#define EDMAREG_SERH 0x3C // Secondary Event Register High Section 11.4.1.106 +#define EDMAREG_SECR 0x40 // Secondary Event Clear Register Section 11.4.1.107 +#define EDMAREG_SECRH 0x44 // Secondary Event Clear Register High Section 11.4.1.108 +#define EDMAREG_IER 0x50 // Interrupt Enable Register Section 11.4.1.109 +#define EDMAREG_IERH 0x54 // Interrupt Enable Register High Section 11.4.1.110 +#define EDMAREG_IECR 0x58 // Interrupt Enable Clear Register Section 11.4.1.111 +#define EDMAREG_IECRH 0x5C // Interrupt Enable Clear Register High Section 11.4.1.112 +#define EDMAREG_IESR 0x60 // Interrupt Enable Set Register Section 11.4.1.113 +#define EDMAREG_IESRH 0x64 // Interrupt Enable Set Register High Section 11.4.1.114 +#define EDMAREG_IPR 0x68 // Interrupt Pending Register Section 11.4.1.115 +#define EDMAREG_IPRH 0x6C // Interrupt Pending Register High Section 11.4.1.116 +#define EDMAREG_ICR 0x70 // Interrupt Clear Register Section 11.4.1.117 +#define EDMAREG_ICRH 0x74 // Interrupt Clear Register High Section 11.4.1.118 +#define EDMAREG_IEVAL 0x78 // Interrupt Evaluate Register Section 11.4.1.119 +#define EDMAREG_QER 0x80 // QDMA Event Register Section 11.4.1.120 +#define EDMAREG_QEER 0x84 // QDMA Event Enable Register Section 11.4.1.121 +#define EDMAREG_QEECR 0x88 // QDMA Event Enable Clear Register Section 11.4.1.122 +#define EDMAREG_QEESR 0x8C // QDMA Event Enable Set Register Section 11.4.1.123 +#define EDMAREG_QSER 0x90 // QDMA Secondary Event Register Section 11.4.1.124 +#define EDMAREG_QSECR 0x94 // QDMA Secondary Event Clear Register Section 11.4.1.125 + +#define EDMA_DCHMAP_N(N) ((0x100 + (N << 2)) / WORDSZ) +#define EDMA_DMAQNUM_0 (0x240 / WORDSZ) // DMA Queue Number Register 0 +#define EDMA_DMAQNUM_1 (0x244 / WORDSZ) // DMA Queue Number Register 1 +#define EDMA_DMAQNUM_2 (0x248 / WORDSZ) // DMA Queue Number Register 2 +#define EDMA_DMAQNUM_3 (0x24C / WORDSZ) // DMA Queue Number Register 3 +#define EDMA_DMAQNUM_4 (0x250 / WORDSZ) // DMA Queue Number Register 4 +#define EDMA_DMAQNUM_5 (0x254 / WORDSZ) // DMA Queue Number Register 5 +#define EDMA_DMAQNUM_6 (0x258 / WORDSZ) // DMA Queue Number Register 6 +#define EDMA_DMAQNUM_7 (0x25C / WORDSZ) // DMA Queue Number Register 7 +#define SHADOW1(reg) ((0x2200 + reg) / WORDSZ) + +// (TRM 11.3.3.1) +#define EDMA_PARAM_OFFSET (0x4000 / WORDSZ) +#define EDMA_PARAM_SIZE sizeof(edmaParam) // 32 bytes +#define EDMA_PARAM_NUM 256 + +// EDMA PARAM registers +typedef struct { + uint32_t sam : 1; + uint32_t dam : 1; + uint32_t syncdim : 1; + uint32_t static_set : 1; + uint32_t : 4; + uint32_t fwid : 3; + uint32_t tccmode : 1; + uint32_t tcc : 6; + uint32_t : 2; + uint32_t tcinten : 1; + uint32_t itcinten : 1; + uint32_t tcchen : 1; + uint32_t itcchen : 1; + uint32_t privid : 4; + uint32_t : 3; + uint32_t priv : 1; +} edmaParamOpt; + +typedef struct { + uint32_t acnt : 16; + uint32_t bcnt : 16; +} edmaParamABcnt; + +typedef struct { + uint32_t srcbidx : 16; + uint32_t dstbidx : 16; +} edmaParamBidx; + +typedef struct { + uint32_t link : 16; + uint32_t bcntrld : 16; +} edmaParamLnkRld; + +typedef struct { + uint32_t srccidx : 16; + uint32_t dstcidx : 16; +} edmaParamCidx; + +typedef struct { + uint32_t ccnt : 16; + uint32_t : 16; +} edmaParamCcnt; + +typedef struct { + edmaParamOpt opt; + uint32_t src; + edmaParamABcnt abcnt; + uint32_t dst; + edmaParamBidx bidx; + edmaParamLnkRld lnkrld; + edmaParamCidx cidx; + edmaParamCcnt ccnt; +} edmaParam; + +#ifdef __cplusplus +} +#endif + +#endif // LIB_DMA_AM335X_DMA_H diff --git a/lib/dma/dma-defs.h b/lib/dma/dma-defs.h new file mode 100644 index 0000000..d881fde --- /dev/null +++ b/lib/dma/dma-defs.h @@ -0,0 +1,19 @@ +// Copyright Joshua MacDonald +// SPDX-License-Identifier: MIT + +#ifndef LIB_DMA_DMA_DEFS_H +#define LIB_DMA_DMA_DEFS_H + +#include "lib/soc/soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void DMA_Init(void); + +#ifdef __cplusplus +} +#endif + +#endif // LIB_DMA_DMA_DEFS_H diff --git a/lib/dma/dma.h b/lib/dma/dma.h new file mode 100644 index 0000000..566e204 --- /dev/null +++ b/lib/dma/dma.h @@ -0,0 +1,23 @@ +// Copyright Joshua MacDonald +// SPDX-License-Identifier: MIT + +#ifndef LIB_DMA_DMA_H +#define LIB_DMA_DMA_H + +#include "lib/dma/dma-defs.h" + +#if defined(SUPRUGLUE_AM335X) +#include "lib/dma/am335x/dma-am335x.h" +#elif defined(SUPRUGLUE_TEST32) +#include "lib/dma/test32/dma-test32.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif // LIB_GPIO_GPIO_H diff --git a/lib/dma/test32/BUILD b/lib/dma/test32/BUILD new file mode 100644 index 0000000..9d63cd5 --- /dev/null +++ b/lib/dma/test32/BUILD @@ -0,0 +1,24 @@ +# -*- Mode: Python -*- +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "test32", + srcs = [ + "dma-test32.cc", + ], + hdrs = [ + "dma-test32.h", + ], + deps = [ + "//lib/dma:defs", + ], +) + +cc_test( + name = "test", + srcs = ["dma_test.cc"], + deps = [ + "//lib/dma", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/lib/dma/test32/dma-test32.cc b/lib/dma/test32/dma-test32.cc new file mode 100644 index 0000000..8db6788 --- /dev/null +++ b/lib/dma/test32/dma-test32.cc @@ -0,0 +1,9 @@ +// Copyright Joshua MacDonald +// SPDX-License-Identifier: MIT + +#include + +#include "dma-test32.h" + +void DMA_Init(void) { +} diff --git a/lib/dma/test32/dma-test32.h b/lib/dma/test32/dma-test32.h new file mode 100644 index 0000000..3995efc --- /dev/null +++ b/lib/dma/test32/dma-test32.h @@ -0,0 +1,20 @@ +// Copyright Joshua MacDonald +// SPDX-License-Identifier: MIT + +#ifndef LIB_DMA_TEST32_DMA_H +#define LIB_DMA_TEST32_DMA_H + +#include + +#include "lib/dma/dma-defs.h" +#include "lib/soc/soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif // LIB_DMA_TEST32_DMA_H diff --git a/lib/dma/test32/dma_test.cc b/lib/dma/test32/dma_test.cc new file mode 100644 index 0000000..3366d45 --- /dev/null +++ b/lib/dma/test32/dma_test.cc @@ -0,0 +1,13 @@ +#include "lib/dma/dma.h" +#include "lib/pinmap/pinmap.h" +#include "lib/soc/soc.h" +#include "gtest/gtest.h" + +class DmaTest : public testing::Test { +protected: + void SetUp() override { + } +}; + +TEST_F(DmaTest, Basic) { +} diff --git a/lib/gpio/am335x/BUILD b/lib/gpio/am335x/BUILD index b8cc475..caea4dc 100644 --- a/lib/gpio/am335x/BUILD +++ b/lib/gpio/am335x/BUILD @@ -3,12 +3,12 @@ package(default_visibility = ["//visibility:public"]) cc_library( name = "am335x", - hdrs = [ - "gpio.h", - ], srcs = [ "gpio.c", ], + hdrs = [ + "gpio.h", + ], deps = [ "//lib/gpio:defs", "//tools/toolchain/am335x", diff --git a/lib/initproc/initproc.c b/lib/initproc/initproc.c index a82dcc5..6c6594e 100644 --- a/lib/initproc/initproc.c +++ b/lib/initproc/initproc.c @@ -17,14 +17,14 @@ void initProcessThread(ThreadID thid, Args args) { uint16_t sz = sizeof(buf); if (ClientRecv(&__transport, buf, &sz) != 0) { - Sleep(TIME_SECOND / 2); + Sleep32(TIME_SECOND / 2); continue; } // Note we do not exit this loop. We needed to do the above once // per firmware start because there is only one host. for (;;) { - Sleep(__system.cfg.export_interval); + Sleep64(__system.cfg.export_interval); Thread *th; for (th = __system.allthreads; th != NULL; th = th->allthreads) { @@ -34,7 +34,7 @@ void initProcessThread(ThreadID thid, Args args) { } } -SUPRUGLUE_DEFINE_THREAD(init, 512); +SUPRUGLUE_DEFINE_THREAD(init, 256); int ProcessInit(void) { Args args; diff --git a/lib/intc/BUILD b/lib/intc/BUILD index 4798920..ec0e24c 100644 --- a/lib/intc/BUILD +++ b/lib/intc/BUILD @@ -13,6 +13,8 @@ cc_library( cc_library( name = "intc", + srcs = [ + ], hdrs = [ "intc.h", ], diff --git a/lib/intc/am335x/intc.c b/lib/intc/am335x/intc.c index 77261c2..3c5f1e8 100644 --- a/lib/intc/am335x/intc.c +++ b/lib/intc/am335x/intc.c @@ -26,6 +26,7 @@ void ControllerInit(void) { uint8_t evt; for (evt = 0; evt < NUM_SYSEVTS; evt++) { __controller.handler[evt] = NULL; + __controller.args[evt].ptr = NULL; } // Disable interrupts until enabled in ControllerEnable(). @@ -36,32 +37,23 @@ void ControllerInit(void) { // this PRU will use. CT_INTC.SECR0 = 0xffffffff; CT_INTC.SECR1 = 0xffffffff; - - // Unset the raw events - CT_INTC.SICR_bit.STS_CLR_IDX = ARM_TO_PRU_EVT; - CT_INTC.SICR_bit.STS_CLR_IDX = SYSEVT_PR1_IEP_TIM_CAP_CMP_PEND; - CT_INTC.SICR_bit.STS_CLR_IDX = SYSEVT_EPWM1_INTR_PEND; } -void InterruptHandlerInit(uint8_t evt, InterruptHandler *handler) { +void InterruptHandlerInit(uint8_t evt, InterruptHandler *handler, Args args) { __controller.handler[evt] = handler; + __controller.args[evt] = args; } void ServiceInterrupts(void) { while ((__R31 & ARM_TO_PRU_IRQ) != 0) { uint8_t evt = HIPRIO_EVT; - // TODO: Can't use debug.h helpers here because they run longer + // Note: Can't use debug.h helpers here because they run longer // than one IEP cycle and lead to an endless interrupt cycle - // because presently, the IEP interrupt has highest priority. - // (Here, 46 is the EPWM1EVT event, which is not working.) - // if (evt == 46) { - // flash(1); - // } // Unblock all and prioritize to run immediately. if (__controller.handler[evt] != NULL) { - (__controller.handler[evt])(); + (__controller.handler[evt])(__controller.args[evt]); } CT_INTC.SICR_bit.STS_CLR_IDX = evt; diff --git a/lib/intc/am335x/intc.h b/lib/intc/am335x/intc.h index db9c034..16121fa 100644 --- a/lib/intc/am335x/intc.h +++ b/lib/intc/am335x/intc.h @@ -16,6 +16,7 @@ struct _InterruptController { // interrupts occupy space, and the lookup is O(1). For now waste // some space. InterruptHandler *handler[NUM_SYSEVTS]; + Args args[NUM_SYSEVTS]; }; #ifdef __cplusplus diff --git a/lib/intc/intc-defs.h b/lib/intc/intc-defs.h index b62bb23..1866d3b 100644 --- a/lib/intc/intc-defs.h +++ b/lib/intc/intc-defs.h @@ -6,19 +6,21 @@ #include +#include "lib/args/args.h" + #ifdef __cplusplus extern "C" { #endif typedef struct _InterruptController InterruptController; -typedef void(InterruptHandler)(void); +typedef void(InterruptHandler)(Args); extern InterruptController __controller; void ControllerInit(void); void ControllerEnable(void); -void InterruptHandlerInit(uint8_t evt, InterruptHandler *handler); +void InterruptHandlerInit(uint8_t evt, InterruptHandler *handler, Args args); void ServiceInterrupts(void); #ifdef __cplusplus diff --git a/lib/intc/test32/intc.cc b/lib/intc/test32/intc.cc index d4e4566..3f0128e 100644 --- a/lib/intc/test32/intc.cc +++ b/lib/intc/test32/intc.cc @@ -21,14 +21,15 @@ struct _TestInterruptController { for (int i = 0; i < NUM_SYSEVTS; i++) { if (_pending[i]) { _pending[i] = false; - _handler[i](); + _handler[i](_args[i]); } } } - void Init(uint8_t evt, InterruptHandler *handler) { + void Init(uint8_t evt, InterruptHandler *handler, Args args) { absl::MutexLock lock(&_lock); _handler[evt] = handler; + _args[evt] = args; } void Raise(uint8_t evt) { @@ -39,6 +40,7 @@ struct _TestInterruptController { absl::Mutex _lock; vector _pending; vector _handler; + vector _args; }; void ControllerInit(void) { @@ -49,8 +51,8 @@ void ServiceInterrupts(void) { __controller.test->Service(); } -void InterruptHandlerInit(uint8_t evt, InterruptHandler *handler) { - __controller.test->Init(evt, handler); +void InterruptHandlerInit(uint8_t evt, InterruptHandler *handler, Args args) { + __controller.test->Init(evt, handler, args); } void RaiseInterrupt(uint8_t evt) { diff --git a/lib/log/daemon/daemon.c b/lib/log/daemon/daemon.c index c213604..e6e81aa 100644 --- a/lib/log/daemon/daemon.c +++ b/lib/log/daemon/daemon.c @@ -19,7 +19,7 @@ void syslogProcess(ThreadID thid, Args args) { while (ClientSend(&__transport, &entry, sizeof(entry)) != 0) { // TODO: Flash user LEDs? - Sleep(TIME_SECOND / 2); + Sleep32(TIME_SECOND / 2); } Yield(); diff --git a/lib/log/journal/journal.c b/lib/log/journal/journal.c index 09ad081..6b56062 100644 --- a/lib/log/journal/journal.c +++ b/lib/log/journal/journal.c @@ -28,7 +28,7 @@ int JournalRead(Journal *jl, Entry *record, JournalReadFlags flags) { if ((flags & JR_BLOCKING) == 0) { return -1; } - SemaDown(&jl->lock); + LockAwait(&jl->lock); } Block *block = BlockListFront(&jl->data); @@ -93,7 +93,7 @@ Entry *getEntry(Journal *jl) { void setEntry(Journal *jl, Entry *entry) { ReadClock(&entry->time); - SemaUp(&jl->lock); + LockWake(&jl->lock); if ((entry->flags & JW_YIELD) != 0) { Yield(); diff --git a/lib/log/journal/journal.h b/lib/log/journal/journal.h index d6063b9..b50c41e 100644 --- a/lib/log/journal/journal.h +++ b/lib/log/journal/journal.h @@ -23,7 +23,7 @@ typedef struct _Entry Entry; typedef struct _Block Block; typedef struct _Integer Integer; -#define NUM_PER_BLOCK 8 +#define NUM_PER_BLOCK 4 #define NUM_BLOCKS 4 SUPRUGLUE_DECLARE_LIST(BlockList, Block); @@ -117,6 +117,16 @@ void setEntry(Journal *jl, Entry *entry); setEntry(&__system.journal, entry); \ } while (0) +#define PRULOG_1u64(level, fmt, arg1) \ + do { \ + Entry *entry = getEntry(&__system.journal); \ + entry->tid = TID(__system_current); \ + entry->flags = JW_##level | JW_FMT_Au64; \ + entry->msg = (fmt); \ + entry->int1.U64 = (arg1); \ + setEntry(&__system.journal, entry); \ + } while (0) + #define PRULOG_2u64(level, fmt, arg1, arg2) \ do { \ Entry *entry = getEntry(&__system.journal); \ diff --git a/lib/pwm/am335x/BUILD b/lib/pwm/am335x/BUILD index 8123058..63d9450 100644 --- a/lib/pwm/am335x/BUILD +++ b/lib/pwm/am335x/BUILD @@ -3,14 +3,15 @@ package(default_visibility = ["//visibility:public"]) cc_library( name = "am335x", - hdrs = [ - "pwm-am335x.h", - ], srcs = [ "pwm-am335x.c", ], + hdrs = [ + "pwm-am335x.h", + ], deps = [ "//lib/pwm:defs", + "//lib/dma/am335x", "//tools/toolchain/am335x", ], ) diff --git a/lib/pwm/am335x/README.md b/lib/pwm/am335x/README.md index 088f5c4..f5b1f37 100644 --- a/lib/pwm/am335x/README.md +++ b/lib/pwm/am335x/README.md @@ -1,3 +1,41 @@ +// OH MY GOODNESS +// TI Compiler uses "interrupt" as a keyword. Can't use this as a C +// variable name and you will get really bad compiler messages if you do! + +// +// 1. The paragraph from 15.2.2.9.3 indicates a connection with the +// DMA controller, but it is unclear whether one needs to be +// concerned with the DMA controller. EDMA channel 35 == ePWMEVT1. +// Do we need a dummy PaRaM entry so that the DMA controller is +// satisfied and will allow interrupts to be generated? +// +// 2. Need to enable the TBCLK for EPWM1 using the PWMSS_CTRL +// register (TRM 9.3.1.31) (offset = 664h) +// +// 3. Need to pinmux the EPWMxA output. +// +// 4. According to some forum threads, the device tree needs to be +// configured to give the PRU control over it. +// See https://e2e.ti.com/support/processors-group/processors/f/processors-forum/918237/am4378-arm-to-pru-event +// See https://forum.beagleboard.org/t/pwmss-control-by-pru-with-kernel-4-19/31246/19 +// Using a device-tree with `status = "disabled"` to prevent the kernel from +// adopting the PWM hardware. +// +// ehrpwm1: pwm@200 { +// compatible = "ti,am3352-ehrpwm"; +// #pwm-cells = <3>; +// reg = <0x200 0x80>; +// clocks = <&ehrpwm1_tbclk>, <&l4ls_gclk>; +// clock-names = "tbclk", "fck"; +// status = "disabled"; +// }; +// +// 5. Searched and searched for any examples or forum discussions on this +// topic, found very little. I assume that anyone trying to the eQEP +// interrupts to work is in the same situation, so here's one: +// +// https://e2e.ti.com/support/processors-group/processors/f/processors-forum/478720/beagle-bone-black-pru-not-able-to-initialize-pwmss0-or-pwmss1 +// https://e2e.ti.com/support/processors-group/processors/f/processors-forum/362435/am335x-unable-to-receive-pwm-interrupt-on-pru Cheatsheet on PWMSS diff --git a/lib/pwm/am335x/epwm1_intr_pend.yaml b/lib/pwm/am335x/epwm1_intr_pend.yaml index c879c67..8818707 100644 --- a/lib/pwm/am335x/epwm1_intr_pend.yaml +++ b/lib/pwm/am335x/epwm1_intr_pend.yaml @@ -1,4 +1,4 @@ incoming: -- event: SYSEVT_EPWM1_INTR_PEND - channel: 4 - desc: eHRPWM interrupt from ePWM module 1 +- event: SYSEVT_TPCC_INT_PEND_PO1 + channel: 5 + desc: EDMA interrupt routed from ePWM module 1 diff --git a/lib/pwm/am335x/pwm-am335x.c b/lib/pwm/am335x/pwm-am335x.c index ffd8721..90d14c9 100644 --- a/lib/pwm/am335x/pwm-am335x.c +++ b/lib/pwm/am335x/pwm-am335x.c @@ -1,17 +1,28 @@ // Copyright Joshua MacDonald // SPDX-License-Identifier: MIT -#include "pwm-am335x.h" +#include +#include + #include "external/ti-pru-support/include/am335x/sys_pwmss.h" -// Status: the code in this directory is a work-in-progress, and not -// completely functional. Here, epwmss1 is initialized with a simple -// counting-up waveform, with: +#include "pwm-am335x.h" + +#define PWM_BASE PWMSS1 + +// TODO: generate DMA event defs +#define EDMA_dmaChannel 15 +#define EDMA_dmaChannelMask (((uint32_t)1) << EDMA_dmaChannel) +#define EDMA_paramNumber EDMA_dmaChannel +#define EDMA_paramNumberMask (((uint32_t)1) << EDMA_paramNumber) + +// Status: // - Prescaler at 1/128 // - Period 10000 // - CMPA 5000 // - CMPB 7500 // - AQ: output low on TBCNT==0, high on TBCNT=CMPA (i.e., 50% duty) +// - Interrupt on CMPB // PWM initialization procedure, from the am335x TRM 15.2.2.2: // @@ -28,71 +39,67 @@ // as DMA events. The interrupt registers should be used to enable and // clear the current DMA event in order for the ePWM module to // generate subsequent DMA events. - -// Various other things we know: -// -// 1. The paragraph from 15.2.2.9.3 indicates a connection with the -// DMA controller, but it is unclear whether one needs to be -// concerned with the DMA controller. EDMA channel 35 == ePWMEVT1. -// Do we need a dummy PaRaM entry so that the DMA controller is -// satisfied and will allow interrupts to be generated? -// -// 2. Need to enable the TBCLK for EPWM1 using the PWMSS_CTRL -// register (TRM 9.3.1.31) (offset = 664h) -// -// 3. Need to pinmux the EPWMxA output. -// -// 4. According to some forum threads, the device tree needs to be -// configured to give the PRU control over it. -// See https://e2e.ti.com/support/processors-group/processors/f/processors-forum/918237/am4378-arm-to-pru-event -// See https://forum.beagleboard.org/t/pwmss-control-by-pru-with-kernel-4-19/31246/19 -// Using a device-tree with `status = "disabled"` to prevent the kernel from -// adopting the PWM hardware. -// -// ehrpwm1: pwm@200 { -// compatible = "ti,am3352-ehrpwm"; -// #pwm-cells = <3>; -// reg = <0x200 0x80>; -// clocks = <&ehrpwm1_tbclk>, <&l4ls_gclk>; -// clock-names = "tbclk", "fck"; -// status = "disabled"; -// }; -// -// 5. Searched and searched for any examples or forum discussions on this -// topic, found very little. I assume that anyone trying to the eQEP -// interrupts to work is in the same situation, so here's one: -// -// https://e2e.ti.com/support/processors-group/processors/f/processors-forum/478720/beagle-bone-black-pru-not-able-to-initialize-pwmss0-or-pwmss1 -// https://e2e.ti.com/support/processors-group/processors/f/processors-forum/362435/am335x-unable-to-receive-pwm-interrupt-on-pru // // Current state: the PWM is configured and running correctly -- the PWM // output can be observed by looping back to a GPIO pin, which the example // `examples/pwm_outin` does. +// Note: The pinmix step has been accomplished, for now, using +// `config-pin P9_14 pwm`. In theory, we can do this with the +// control module: +// +// CONTROL_MODULE[0x848 / WORDSZ] = (6 << 0); // P9_14 == Mode 6 + // PWM_ClearInterrupt is called from the interrupt servicing routine. // void PWM_ClearInterrupt(void) { - // Experimental: do we need to clear a DMA interrupt, too? - // EDMA_BASE[SHADOW1(EDMAREG_ICRH)] = EDMA_dmaChannelMask; + // Important! Clear the DMA interrupt, THEN clear the DMA trigger + // event. + EDMA_BASE[SHADOW1(EDMAREG_ICRH)] = 1U << 31; + + // Clear the DMA event. Note this shoul + EDMA_BASE[SHADOW1(EDMAREG_ECR)] = EDMA_dmaChannelMask; + + // if (EDMA_BASE[SHADOW1(EDMAREG_ICRH)] & (1U << 31) != 0) { + PWM_BASE.EPWM_ETCLR = 1; - // Clear the event. - PWMSS1.EPWM_ETCLR = 1; + // TRM says to do this when there are still IPR or IPRH + // bits set. Seems OK to be unconditional. + EDMA_BASE[SHADOW1(EDMAREG_IEVAL)] = 1; } // PWM_Init initializes but does not start the PWM. -void PWM_Init(void) { +void PWM_Init(int32_t LH, int32_t P, int32_t I) { + + // Enable the PWM clock. + + PWM_BASE.CLKCONFIG_bit.EPWMCLK_EN = 1; + PWM_BASE.SYSCONFIG_bit.IDLEMODE = 2; + + ////////////////////////////////////////////////////////////////////// + // Control module + CONTROL_MODULE[0x664 / WORDSZ] = (1 << 1); // Enable TBCLK for EPWM1 + + // DO NOT DO THIS: You can't setup the peripheral when the + // (not sure) interface or functional clock is disabled. + // ////////////////////////////////////////////////////////////////////// + // Control module + // CONTROL_MODULE[0x664 / WORDSZ] = (0 << 1); // Enable TBCLK for EPWM1 + // Enable the PWM clock. + // PWM_BASE.CLKCONFIG_bit.EPWMCLK_EN = 0; + ////////////////////////////////////////////////////////////////////// // Time-Base - PWMSS1.EPWM_TBCTL = (3 << 14) | // FREE_SOFT: Free run - (0 << 13) | // PHSDIR: n/a in up-count mode - (7 << 10) | // CLKDIV: Time-base clock prescale bits (/128) - (1 << 7) | // HSPCLKDIV: (Default) high-speed clock prescale bits - (0 << 6) | // SWFSYNC: No force sync pulse - (0 << 4) | // SYNCOSEL: Sync output from EPWMxSYNC - (0 << 3) | // PRDLD: Load active period from shadow - (0 << 2) | // PHSEN: Do not load from time-base phase register - (0 << 0); // CTRMODE: Up-count mode + PWM_BASE.EPWM_TBCTL = (0 << 14) | // FREE_SOFT: Disabled. + (0 << 13) | // PHSDIR: n/a in up-count mode + (7 << 10) | // CLKDIV: Time-base clock prescale bits (/128) + (1 << 7) | // HSPCLKDIV: (Default) high-speed clock prescale bits + (0 << 6) | // SWFSYNC: No force sync pulse + (0 << 4) | // SYNCOSEL: Sync output from EPWMxSYNC + (0 << 3) | // PRDLD: Load active period from shadow + (0 << 2) | // PHSEN: Do not load from time-base phase register + (0 << 0); // CTRMODE: Up-count mode // TBSTS: All defaults // TBPHSHR: Not used @@ -105,23 +112,24 @@ void PWM_Init(void) { // CMPA: Not used // CMPAHR: Not used - PWMSS1.EPWM_TBPRD = 10000; // TBPRD: Time-base period (16 bits) + PWM_BASE.EPWM_TBCNT = 0; // TBCNT: Time-base clock (16 bits) + PWM_BASE.EPWM_TBPRD = P; // TBPRD: Time-base period (16 bits) // CMPCTL: All defaults // CMPAHR: Not used - PWMSS1.EPWM_CMPA = 5000; // CMPB: Compare value for clearing EPWMxA - PWMSS1.EPWM_CMPB = 7500; // CMPB: Compare value for sample interrupt + PWM_BASE.EPWM_CMPA = LH; // CMPB: Compare value for clearing EPWMxA + PWM_BASE.EPWM_CMPB = I; // CMPB: Compare value for sample interrupt ////////////////////////////////////////////////////////////////////// // Action qualifier - PWMSS1.EPWM_AQCTLA = (2 << 0) | // ZRO: force EPWMxA low when TBCNT == 0 - (1 << 4); // CAU: force EPWMxA high when TBCNT == CMPA + PWM_BASE.EPWM_AQCTLA = (2 << 0) | // ZRO: force EPWMxA high when TBCNT == 0 + (1 << 4); // CAU: force EPWMxA low when TBCNT == CMPA // AQCTLB: Not used - // PWMSS1.EPWM_AQSFRC = (3 << 6); // Immediate mode - // PWMSS1.EPWM_AQCSFRC = (1 << 0); // Force low on EPWMxA + // PWM_BASE.EPWM_AQSFRC = (3 << 6); // Immediate mode + // PWM_BASE.EPWM_AQCSFRC = (1 << 0); // Force low on EPWMxA ////////////////////////////////////////////////////////////////////// // Chopper: Not used @@ -130,64 +138,49 @@ void PWM_Init(void) { ////////////////////////////////////////////////////////////////////// // Event trigger - PWMSS1.EPWM_ETSEL = (6 << 0); // INTSEL: CMPB incrementing - PWMSS1.EPWM_ETPS = (1 << 0); // INTPRD: Every event - - // Clear pending interrupt! - PWMSS1.EPWM_ETCLR = (1 << 0); - - ////////////////////////////////////////////////////////////////////// - // Control module - CONTROL_MODULE[0x664 / WORDSZ] = (1 << 1); // Enable TBCLK for EPWM1 - - // Note: The pinmix step has been accomplished, for now, using - // `config-pin P9_14 pwm`. In theory, we can do this with the - // control module: - // - // CONTROL_MODULE[0x848 / WORDSZ] = (6 << 0); // P9_14 == Mode 6 - - // Enable the PWM clock. - PWMSS1.CLKCONFIG_bit.EPWMCLK_EN = 1; + PWM_BASE.EPWM_ETCLR = (1 << 0); // Clear pending interrupt + PWM_BASE.EPWM_ETSEL = (6 << 0); // INTSEL: CMPB incrementing + PWM_BASE.EPWM_ETPS = (1 << 0); // INTPRD: Every event + // DMA setup // The following experimental code attempts to create a dummy PaRaM - // entry, attempting to see if helps with the issue described in - // 15.2.2.9.3. It does not appear to help. + // entry, because there appears to be no way to "just send an event" + // to one of the interrupt controllers. -#if 0 // Setup EDMA region access for Shadow Region 1 // Note the Linux kernel uses Shadow Region 0. // // DRAE1 == DMA Region Access Enable shadow region 1. // // We enable a single channel in this region. - EDMA_BASE[EDMA_DRAEH1] = EDMA_dmaChannelMask; - EDMA_BASE[EDMA_DRAEH1] = EDMA_paramNumberMask; + EDMA_BASE[EDMA_DRAE1] = EDMA_dmaChannelMask; + EDMA_BASE[EDMA_DRAEH1] = 1U << 31; - // // Map DMA Channel to PaRAM w/ same number. + // Map DMA Channel to PaRAM w/ same number. EDMA_BASE[EDMA_DCHMAP_N(EDMA_dmaChannel)] = EDMA_paramNumber << 5; - // // Setup channel to submit to EDMA TC0 (highest priority). - // // - // // Note DMAQNUM_5 configures the channel controller for channels - // // 32-39. This is specific to channel 35. - EDMA_BASE[EDMA_DMAQNUM_4] &= 0xFFFF8FFF; - - // // Enable channel for an event trigger. - // EDMA_BASE[SHADOW1(EDMAREG_EESRH)] = EDMA_dmaChannelMask; + // Note DMAQNUM_1 configures the channel controller for channels + // 8-15. This is specific to channel 15 => queue 2. + EDMA_BASE[EDMA_DMAQNUM_1] = 0x20000000; - EDMA_BASE[SHADOW1(EDMAREG_IESRH)] = EDMA_dmaChannelMask; + // Enable channel for an event trigger. + EDMA_BASE[SHADOW1(EDMAREG_EESR)] = EDMA_dmaChannelMask; + EDMA_BASE[SHADOW1(EDMAREG_ICR)] = EDMA_dmaChannelMask; - // // Clear interrupt and secondary event registers. - EDMA_BASE[SHADOW1(EDMAREG_SECRH)] = EDMA_dmaChannelMask; + // Clear and enable the register (was added to shadow region above) + EDMA_BASE[SHADOW1(EDMAREG_ICRH)] = 1U << 31; // which is event 63 + EDMA_BASE[SHADOW1(EDMAREG_IESRH)] = 1U << 31; // which is event 63 - // // Clear event missed register. - // EDMA_BASE[EDMA_EMCRH] = EDMA_dmaChannelMask; + // Clear secondary & missed register + EDMA_BASE[SHADOW1(EDMAREG_SECR)] = EDMA_dmaChannelMask; + EDMA_BASE[EDMA_EMCR] = EDMA_dmaChannelMask; - // // Setup and store Dummy PaRAM. + // Setup and store Dummy PaRAM. uint16_t paramOffset = EDMA_PARAM_OFFSET; paramOffset += ((EDMA_paramNumber * EDMA_PARAM_SIZE) / WORDSZ); volatile edmaParam *edma_param_entry = (volatile edmaParam *)(EDMA_BASE + paramOffset); + memset((void *)edma_param_entry, 0, sizeof(*edma_param_entry)); edma_param_entry->lnkrld.link = 0xFFFF; edma_param_entry->lnkrld.bcntrld = 0x0000; @@ -195,19 +188,29 @@ void PWM_Init(void) { // Transfer complete interrupt enable. edma_param_entry->opt.tcinten = 1; - - // Intermediate transfer completion chaining enable. - // not needed, used for splitting the transfer - // edma_param_entry->opt.itcchen = 1; - edma_param_entry->opt.tcc = EDMA_dmaChannel; + edma_param_entry->opt.tcc = 63; edma_param_entry->ccnt.ccnt = 1; - edma_param_entry->abcnt.acnt = 0; + edma_param_entry->abcnt.acnt = 1; edma_param_entry->abcnt.bcnt = 1; -#endif + edma_param_entry->src = 0x10000 + 1; + edma_param_entry->dst = 0x10000; } // PWM_Enable enables PWM interrupts. void PWM_Enable(void) { - PWMSS1.EPWM_ETSEL |= (1 << 3); + PWM_BASE.EPWM_TBCTL |= (3 << 14); // FREE_SOFT: Free run + + ////////////////////////////////////////////////////////////////////// + // Control module + CONTROL_MODULE[0x664 / WORDSZ] = (1 << 1); // Enable TBCLK for EPWM1 + + PWM_BASE.EPWM_ETSEL = (1 << 3) | // Interrupts enabled + (6 << 0); // Interrupt on CMB-B == TBCNT + + PWM_ClearInterrupt(); +} + +void PWM_Disable(void) { + PWM_BASE.EPWM_TBCTL &= ~(3 << 14); // FREE_SOFT: Free run } diff --git a/lib/pwm/am335x/pwm-am335x.h b/lib/pwm/am335x/pwm-am335x.h index af27537..ae3f581 100644 --- a/lib/pwm/am335x/pwm-am335x.h +++ b/lib/pwm/am335x/pwm-am335x.h @@ -1,146 +1,16 @@ // Copyright Joshua MacDonald // SPDX-License-Identifier: MIT -#include "lib/pwm/pwm-defs.h" - #ifndef LIB_PWM_AM335X_PWM_H #define LIB_PWM_AM335X_PWM_H +#include "lib/dma/am335x/dma-am335x.h" +#include "lib/pwm/pwm-defs.h" + #ifdef __cplusplus extern "C" { #endif -// Note! All of these constants belong in a better place and should -// probably be auto-generated. I've placed them here to see if -// configuring a dummy PaRaM entry on the ehrpwm1 DMA channel would -// help with interrupt generation. - -// This DMA code was copied from another project, which succeeded at -// receiving an interrupt on the PRU from the DMA controller. See: -// -// https://forum.beagleboard.org/t/kernel-5-10-device-tree-overlay-for-using-dma-from-bbb-pru/35665 - -#define CONTROL_MODULE ((uint32_t *)0x44E10000) - -#define EDMA_BASE ((volatile uint32_t *)(0x49000000)) -#define EDMA_DRAE1 (0x348 / WORDSZ) // DMA Region Access Enable Register for Region 1 Section 11.4.1.20 -#define EDMA_DRAEH1 (0x34C / WORDSZ) // DMA Region Access Enable Register High for Region 1 Section 11.4.1.21 - -#define EDMA_EMR (0x300 / WORDSZ) // Event Missed Register Section 11.4.1.9 -#define EDMA_EMRH (0x304 / WORDSZ) // Event Missed Register High Section 11.4.1.10 -#define EDMA_EMCR (0x308 / WORDSZ) // Event Missed Clear Register Section 11.4.1.11 -#define EDMA_EMCRH (0x30C / WORDSZ) // Event Missed Clear Register High Section 11.4.1.12 - -#define EDMA_CCERR (0x318 / WORDSZ) // EDMA3CC Error Register Section 11.4.1.15 -#define EDMA_EEVAL (0x320 / WORDSZ) // EDMA3CC EEVAL -#define EDMA_CCERRCLR (0x31C / WORDSZ) // EDMA3CC Error Clear Register Section 11.4.1.16 - -#define EDMAREG_ER 0x00 // Event Register Section 11.4.1.91 -#define EDMAREG_ERH 0x04 // Event Register High Section 11.4.1.92 -#define EDMAREG_ECR 0x08 // Event Clear Register Section 11.4.1.93 -#define EDMAREG_ECRH 0x0C // Event Clear Register High Section 11.4.1.94 -#define EDMAREG_ESR 0x10 // Event Set Register Section 11.4.1.95 -#define EDMAREG_ESRH 0x14 // Event Set Register High Section 11.4.1.96 -#define EDMAREG_CER 0x18 // Chained Event Register Section 11.4.1.97 -#define EDMAREG_CERH 0x1C // Chained Event Register High Section 11.4.1.98 -#define EDMAREG_EER 0x20 // Event Enable Register Section 11.4.1.99 -#define EDMAREG_EERH 0x24 // Event Enable Register High Section 11.4.1.100 -#define EDMAREG_EECR 0x28 // Event Enable Clear Register Section 11.4.1.101 -#define EDMAREG_EECRH 0x2C // Event Enable Clear Register High Section 11.4.1.102 -#define EDMAREG_EESR 0x30 // Event Enable Set Register Section 11.4.1.103 -#define EDMAREG_EESRH 0x34 // Event Enable Set Register High Section 11.4.1.104 -#define EDMAREG_SER 0x38 // Secondary Event Register Section 11.4.1.105 -#define EDMAREG_SERH 0x3C // Secondary Event Register High Section 11.4.1.106 -#define EDMAREG_SECR 0x40 // Secondary Event Clear Register Section 11.4.1.107 -#define EDMAREG_SECRH 0x44 // Secondary Event Clear Register High Section 11.4.1.108 -#define EDMAREG_IER 0x50 // Interrupt Enable Register Section 11.4.1.109 -#define EDMAREG_IERH 0x54 // Interrupt Enable Register High Section 11.4.1.110 -#define EDMAREG_IECR 0x58 // Interrupt Enable Clear Register Section 11.4.1.111 -#define EDMAREG_IECRH 0x5C // Interrupt Enable Clear Register High Section 11.4.1.112 -#define EDMAREG_IESR 0x60 // Interrupt Enable Set Register Section 11.4.1.113 -#define EDMAREG_IESRH 0x64 // Interrupt Enable Set Register High Section 11.4.1.114 -#define EDMAREG_IPR 0x68 // Interrupt Pending Register Section 11.4.1.115 -#define EDMAREG_IPRH 0x6C // Interrupt Pending Register High Section 11.4.1.116 -#define EDMAREG_ICR 0x70 // Interrupt Clear Register Section 11.4.1.117 -#define EDMAREG_ICRH 0x74 // Interrupt Clear Register High Section 11.4.1.118 -#define EDMAREG_IEVAL 0x78 // Interrupt Evaluate Register Section 11.4.1.119 -#define EDMAREG_QER 0x80 // QDMA Event Register Section 11.4.1.120 -#define EDMAREG_QEER 0x84 // QDMA Event Enable Register Section 11.4.1.121 -#define EDMAREG_QEECR 0x88 // QDMA Event Enable Clear Register Section 11.4.1.122 -#define EDMAREG_QEESR 0x8C // QDMA Event Enable Set Register Section 11.4.1.123 -#define EDMAREG_QSER 0x90 // QDMA Secondary Event Register Section 11.4.1.124 -#define EDMAREG_QSECR 0x94 // QDMA Secondary Event Clear Register Section 11.4.1.125 - -#define EDMA_DCHMAP_N(N) ((0x100 + (N << 2)) / WORDSZ) -#define EDMA_DMAQNUM_4 (0x250 / WORDSZ) // DMA Queue Number Register 4 -#define SHADOW1(reg) ((0x2200 + reg) / WORDSZ) - -#define EDMA_dmaChannel 35 -#define EDMA_dmaChannelMask (1 << (EDMA_dmaChannel - 32)) -#define EDMA_paramNumber EDMA_dmaChannel -#define EDMA_paramNumberMask (1 << (EDMA_paramNumber - 32)) - -// (TRM 11.3.3.1) -#define EDMA_PARAM_OFFSET (0x4000 / WORDSZ) -#define EDMA_PARAM_SIZE sizeof(edmaParam) // 32 bytes -#define EDMA_PARAM_NUM 256 - -// EDMA PARAM registers -typedef struct { - uint32_t sam : 1; - uint32_t dam : 1; - uint32_t syncdim : 1; - uint32_t static_set : 1; - uint32_t : 4; - uint32_t fwid : 3; - uint32_t tccmode : 1; - uint32_t tcc : 6; - uint32_t : 2; - uint32_t tcinten : 1; - uint32_t itcinten : 1; - uint32_t tcchen : 1; - uint32_t itcchen : 1; - uint32_t privid : 4; - uint32_t : 3; - uint32_t priv : 1; -} edmaParamOpt; - -typedef struct { - uint32_t acnt : 16; - uint32_t bcnt : 16; -} edmaParamABcnt; - -typedef struct { - uint32_t srcbidx : 16; - uint32_t dstbidx : 16; -} edmaParamBidx; - -typedef struct { - uint32_t link : 16; - uint32_t bcntrld : 16; -} edmaParamLnkRld; - -typedef struct { - uint32_t srccidx : 16; - uint32_t dstcidx : 16; -} edmaParamCidx; - -typedef struct { - uint32_t ccnt : 16; - uint32_t : 16; -} edmaParamCcnt; - -typedef struct { - edmaParamOpt opt; - uint32_t src; - edmaParamABcnt abcnt; - uint32_t dst; - edmaParamBidx bidx; - edmaParamLnkRld lnkrld; - edmaParamCidx cidx; - edmaParamCcnt ccnt; -} edmaParam; - #ifdef __cplusplus } #endif diff --git a/lib/pwm/pwm-defs.h b/lib/pwm/pwm-defs.h index 20858e0..01e3b55 100644 --- a/lib/pwm/pwm-defs.h +++ b/lib/pwm/pwm-defs.h @@ -4,15 +4,16 @@ #ifndef LIB_PWM_PWM_DEFS_H #define LIB_PWM_PWM_DEFS_H +#include "lib/soc/soc.h" + #ifdef __cplusplus extern "C" { #endif -#include "lib/soc/soc.h" - -void PWM_Init(void); +void PWM_Init(int32_t lowhigh, int32_t period, int32_t inter); void PWM_ClearInterrupt(void); void PWM_Enable(void); +void PWM_Disable(void); #ifdef __cplusplus } diff --git a/lib/resource/BUILD b/lib/resource/BUILD index 8b27c8a..85cd906 100644 --- a/lib/resource/BUILD +++ b/lib/resource/BUILD @@ -9,11 +9,11 @@ cc_library( hdrs = [ "table.h", ], - deps = [ - "@ti-pru-support//include", - ], target_compatible_with = select({ "//tools/toolchain:am335x": [], "//conditions:default": ["@platforms//:incompatible"], }), + deps = [ + "@ti-pru-support//include", + ], ) diff --git a/lib/rpmsg/am335x/rpmsg.c b/lib/rpmsg/am335x/rpmsg.c index 46aa511..a1da9ff 100644 --- a/lib/rpmsg/am335x/rpmsg.c +++ b/lib/rpmsg/am335x/rpmsg.c @@ -31,7 +31,7 @@ ClientTransport __transport; void RpmsgKick(void) { // Note: this can wake > 1 - SemaUp(&__transport.kick_lock); + LockWake(&__transport.kick_lock); } // These two system events are wired to the PRU automatically by the @@ -70,9 +70,11 @@ int RpmsgInit(ClientTransport *transport, struct fw_rsc_vdev *vdev, struct fw_rs while (!(*status & VIRTIO_CONFIG_S_DRIVER_OK)) { } + Args args; + // The system events and port are core-specific. #if SUPRUGLUE_PRU_NUM == 0 - InterruptHandlerInit(SYSEVT_PR1_PRU_MST_INTR1_INTR_REQ, &RpmsgKick); + InterruptHandlerInit(SYSEVT_PR1_PRU_MST_INTR1_INTR_REQ, &RpmsgKick, args); // @@@ transport->channel_port = RPMSG_CHANNEL_PORT_0; sysevt_pru_to_arm = SYSEVT_PR1_PRU_MST_INTR0_INTR_REQ; @@ -104,14 +106,14 @@ int RpmsgInit(ClientTransport *transport, struct fw_rsc_vdev *vdev, struct fw_rs int ClientSend(ClientTransport *transport, const void *data, uint16_t len) { if (transport->peer_src_addr == 0) { // In case we have never received. - SemaDown(&transport->peer_lock); + LockAwait(&transport->peer_lock); } int err = pru_rpmsg_send(&transport->channel, transport->peer_dst_addr, transport->peer_src_addr, (void *)data, len); if (err != 0) { // IS THIS HAPPENING? OR THE ABOVE? We are copying from an address on the stack // and what ... can it move? @@@ Hmm, nope. - SemaDown(&transport->kick_lock); + LockAwait(&transport->kick_lock); } return err; } @@ -121,11 +123,11 @@ int ClientRecv(ClientTransport *transport, void *data, uint16_t *len) { int err = pru_rpmsg_receive(&transport->channel, &transport->peer_src_addr, &transport->peer_dst_addr, data, len); if (err != 0) { - SemaDown(&transport->kick_lock); + LockAwait(&transport->kick_lock); return err; } if (was_unset != 0 && transport->peer_src_addr != 0) { - SemaUp(&transport->peer_lock); + LockWake(&transport->peer_lock); } return 0; } diff --git a/lib/soc/am335x/soc.h b/lib/soc/am335x/soc.h index e577728..c397d71 100644 --- a/lib/soc/am335x/soc.h +++ b/lib/soc/am335x/soc.h @@ -24,6 +24,10 @@ extern void SystemOnChipSuspend(void); #define ARCH_NUM_SYSEVTS 64 +// Control module base address (Pinmux, DMA crossbar, etc.) -- +// See TRM section 9. +#define CONTROL_MODULE ((uint32_t *)0x44e10000) + #ifdef __cplusplus } #endif diff --git a/lib/soc/soc-defs.h b/lib/soc/soc-defs.h index 0d94e29..f9647e4 100644 --- a/lib/soc/soc-defs.h +++ b/lib/soc/soc-defs.h @@ -19,9 +19,13 @@ extern "C" { type2 space[size]; \ } +// TODO: The once-DATA_SECTION below was incorrect. It causes the +// compiler to place this data in the text section, probably because +// it is page zero and there is not a linker command entry for the +// section names produced here. + #define SUPRUGLUE_DEFINE_SIZED(name, type1, thing1, type2, size) \ SUPRUGLUE_DECLARE_SIZED(name, type1, thing1, type2, size); \ - _PRAGMA(DATA_SECTION(name, ".thread." #name)) \ static SUPRUGLUE_SIZED_TYPENAME(name, type1, type2) name #ifdef SUPRUGLUE_TEST32 diff --git a/lib/sync/sync.c b/lib/sync/sync.c index b6cb844..76875a9 100644 --- a/lib/sync/sync.c +++ b/lib/sync/sync.c @@ -7,14 +7,36 @@ void LockInit(LockWord *word) { ThreadListInit(&word->waiters); } -void SemaDown(LockWord *word) { +void LockAwait(LockWord *word) { ThreadListPushBack(&word->waiters, __system_current); YieldBlocked(); } -void SemaUp(LockWord *word) { +void LockWake(LockWord *word) { while (!ThreadListEmpty(&word->waiters)) { Thread *wake = ThreadListPopFront(&word->waiters); ThreadListPushFront(&__system_runnable, wake); } } + +void SemaphoreInit(Semaphore *semaphore) { + LockInit(&semaphore->lock); + semaphore->value = 0; +} + +void SemaphoreUp(Semaphore *semaphore) { + if (!ThreadListEmpty(&semaphore->lock.waiters)) { + Thread *wake = ThreadListPopFront(&semaphore->lock.waiters); + ThreadListPushFront(&__system_runnable, wake); + return; + } + semaphore->value++; +} + +void SemaphoreDown(Semaphore *semaphore) { + if (semaphore->value > 0) { + semaphore->value--; + return; + } + LockAwait(&semaphore->lock); +} diff --git a/lib/sync/sync.h b/lib/sync/sync.h index 3ff5b18..0c8e4eb 100644 --- a/lib/sync/sync.h +++ b/lib/sync/sync.h @@ -16,13 +16,25 @@ struct _LockWord; typedef struct _LockWord LockWord; struct _LockWord { - // This code supports primitive sleep/wake, rename methods? ThreadList waiters; }; void LockInit(LockWord *lockword); -void SemaDown(LockWord *lockword); -void SemaUp(LockWord *lockword); +void LockAwait(LockWord *lockword); +void LockWake(LockWord *lockword); + +struct _Semaphore; + +typedef struct _Semaphore Semaphore; + +struct _Semaphore { + LockWord lock; + int32_t value; +}; + +void SemaphoreInit(Semaphore *semaphore); +void SemaphoreUp(Semaphore *semaphore); +void SemaphoreDown(Semaphore *semaphore); #ifdef __cplusplus } diff --git a/lib/time/am335x/clock-am335x.c b/lib/time/am335x/clock-am335x.c index 5aa8259..3390771 100644 --- a/lib/time/am335x/clock-am335x.c +++ b/lib/time/am335x/clock-am335x.c @@ -27,10 +27,10 @@ void UpdateClock(void) { __clock.CYCLES_bit.LOW = ts; } -void ClockHandler(void) { +void ClockHandler(Args args) { CT_IEP.TMR_CMP_STS_bit.CMP_HIT = 0x1; - SemaUp(&__clock_lock); + LockWake(&__clock_lock); UpdateClock(); } @@ -49,7 +49,10 @@ void TimeInit(void) { CT_IEP.TMR_CMP_CFG_bit.CMP_EN = 0x1; // CMP[0] enabled CT_IEP.TMR_CMP_CFG_bit.CMP0_RST_CNT_EN = 0x1; // CMP[0] will reset - InterruptHandlerInit(SYSEVT_PR1_IEP_TIM_CAP_CMP_PEND, ClockHandler); + Args args; + args.ptr = ""; + + InterruptHandlerInit(SYSEVT_PR1_IEP_TIM_CAP_CMP_PEND, ClockHandler, args); } void TimeStart(void) { diff --git a/lib/time/am335x/clock-am335x.h b/lib/time/am335x/clock-am335x.h index bed6943..7b796ca 100644 --- a/lib/time/am335x/clock-am335x.h +++ b/lib/time/am335x/clock-am335x.h @@ -10,7 +10,8 @@ extern "C" { #endif -#define TIME_SECOND 200000000 +#define TIME_SECOND ((uint32_t)200000000) +#define TIME_SECOND64 ((uint64_t)200000000) extern Timestamp __clock; diff --git a/lib/time/clock.c b/lib/time/clock.c index 83253f1..00c8151 100644 --- a/lib/time/clock.c +++ b/lib/time/clock.c @@ -9,10 +9,23 @@ LockWord __clock_lock; ThreadList __asleep; -void SleepUntil(Timestamp *when, uint32_t cycles) { +void SleepUntil32(Timestamp *when, uint32_t cycles) { Thread *self = __system_current; - TimeAddCycles(when, cycles); + TimeAddCycles32(when, cycles); + self->when = *when; + + ThreadListPushBack(&__asleep, self); + YieldBlocked(); + + // Note: the clock process could set the wakeup time as self->when + // and the difference could be use to detect falling behind, maybe. +} + +void SleepUntil64(Timestamp *when, uint64_t cycles) { + Thread *self = __system_current; + + TimeAddCycles64(when, cycles); self->when = *when; ThreadListPushBack(&__asleep, self); diff --git a/lib/time/clock.h b/lib/time/clock.h index c65082b..f6cafca 100644 --- a/lib/time/clock.h +++ b/lib/time/clock.h @@ -18,15 +18,27 @@ extern "C" { #include "lib/time/test32/clock-test32.h" #endif -void Sleep(uint32_t cycles); -void TimeAddCycles(Timestamp *clock, uint32_t cycles); -void SleepUntil(Timestamp *when, uint32_t cycles); +void Sleep32(uint32_t cycles); +void TimeAddCycles32(Timestamp *clock, uint32_t cycles); +void SleepUntil32(Timestamp *when, uint32_t cycles); -inline void Sleep(uint32_t cycles) { - SleepUntil(&__system_current->when, cycles); +inline void Sleep32(uint32_t cycles) { + SleepUntil32(&__system_current->when, cycles); } -inline void TimeAddCycles(Timestamp *clock, uint32_t cycles) { +inline void TimeAddCycles32(Timestamp *clock, uint32_t cycles) { + clock->CYCLES += cycles; +} + +void Sleep64(uint64_t cycles); +void TimeAddCycles64(Timestamp *clock, uint64_t cycles); +void SleepUntil64(Timestamp *when, uint64_t cycles); + +inline void Sleep64(uint64_t cycles) { + SleepUntil64(&__system_current->when, cycles); +} + +inline void TimeAddCycles64(Timestamp *clock, uint64_t cycles) { clock->CYCLES += cycles; } diff --git a/lib/time/clock_test.cc b/lib/time/clock_test.cc index a081833..651a5c5 100644 --- a/lib/time/clock_test.cc +++ b/lib/time/clock_test.cc @@ -19,7 +19,7 @@ void test_write_func(ThreadID tid, Args args) { int32_t cnt = Atoi(args.ptr); for (int32_t i = 0; i < cnt; i++) { PRULOG_1u32(INFO_NOYIELD, "write %u", i); // Logs always yield - Sleep(10); + Sleep32(10); } } diff --git a/lib/time/process.c b/lib/time/process.c index a84dd06..9154f98 100644 --- a/lib/time/process.c +++ b/lib/time/process.c @@ -14,7 +14,7 @@ SUPRUGLUE_DEFINE_THREAD(clockproc, 256); void clockProcess(ThreadID thid, Args args) { for (;;) { - SemaDown(&__clock_lock); + LockAwait(&__clock_lock); Timestamp clk; ReadClock(&clk); diff --git a/lib/time/test32/clock-test32.cc b/lib/time/test32/clock-test32.cc index 351a3d9..afd30ea 100644 --- a/lib/time/test32/clock-test32.cc +++ b/lib/time/test32/clock-test32.cc @@ -17,12 +17,13 @@ high_resolution_clock::time_point started; high_resolution_clock::time_point switched; thread *source; -void Tick(void) { - SemaUp(&__clock_lock); +void Tick(Args args) { + LockWake(&__clock_lock); } void TimeInit(void) { - InterruptHandlerInit(1, Tick); + Args args = {.ptr = NULL}; + InterruptHandlerInit(1, Tick, args); source = new thread([] { for (;;) { usleep(10000); diff --git a/lib/time/test32/clock-test32.h b/lib/time/test32/clock-test32.h index db47bd8..6c0ba22 100644 --- a/lib/time/test32/clock-test32.h +++ b/lib/time/test32/clock-test32.h @@ -10,7 +10,8 @@ extern "C" { #include "lib/time/clock-defs.h" -#define TIME_SECOND 10000000 +#define TIME_SECOND ((uint32_t)10000000) +#define TIME_SECOND64 ((uint64_t)10000000) #ifdef __cplusplus } diff --git a/lib/ui1203/BUILD b/lib/ui1203/BUILD index ff2218c..e5d877e 100644 --- a/lib/ui1203/BUILD +++ b/lib/ui1203/BUILD @@ -1,22 +1,30 @@ # -*- Mode: Python -*- package(default_visibility = ["//visibility:public"]) -# cc_library( -# name = "ui1203", -# srcs = [ -# "ui1203.c", -# ], -# hdrs = [ -# "ui1203.h", -# ], -# deps = ["//lib/gpio"], -# ) +cc_library( + name = "ui1203", + srcs = [ + "ui1203.c", + ], + hdrs = [ + "ui1203.h", + ], + deps = [ + "//lib/gpio", + "//lib/pwm", + "//lib/cap", + "//lib/sync", + "//lib/time", + "//lib/coroutine", + "//lib/log/journal", + ], +) -# cc_test( -# name = "test", -# srcs = ["ui1203_test.cc"], -# deps = [ -# ":ui1203", -# "@com_google_googletest//:gtest_main", -# ], -# ) +cc_test( + name = "test", + srcs = ["ui1203_test.cc"], + deps = [ + ":ui1203", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/lib/ui1203/ui1203.c b/lib/ui1203/ui1203.c index e3c755a..1eff42d 100644 --- a/lib/ui1203/ui1203.c +++ b/lib/ui1203/ui1203.c @@ -2,14 +2,174 @@ // SPDX-License-Identifier: MIT #include "lib/ui1203/ui1203.h" +#include "lib/cap/cap.h" +#include "lib/coroutine/coroutine.h" +#include "lib/gpio/gpio.h" +#include "lib/intc/intc.h" +#include "lib/log/journal/journal.h" +#include "lib/pwm/pwm.h" +#include "lib/soc/sysevts.h" +#include "lib/sync/sync.h" +#include "lib/time/clock.h" #include -// void UI1203_Init_Reader(UI1203_Reader *rdr, gpio_pin clock, gpio_pin data) { -// rdr->clock = clock; -// rdr->data = data; -// } +void readerHandler(Args args) { + UI1203_Reader *rdr = (UI1203_Reader *)args.ptr; + SemaphoreUp(&rdr->sem); -// void UI1203_Run_Reader(UI1203_Reader *rdr) { -// // Placeholder! @@@ -// // printf("Running!!\n"); -// } + // PRULOG_0(INFO_NOYIELD, "pwm interrupt"); + + PWM_ClearInterrupt(); +} + +void readerRunner(ThreadID tid, Args args) { + UI1203_Reader *rdr = (UI1203_Reader *)args.ptr; + Timestamp clock; + ReadClock(&clock); + + while (1) { + // Reset state + uint16_t position = 0; + uint16_t byte = 0; + uint16_t count = 0; + + // PWM_Enable(); + + for (; position < 32;) { + // V;RBxxxxxxx;IByyyyy;Kmmmmm\r + // or + // Rxxxxyyyyyyyy\r + + // Note that ASCII: + // '0' is 0x30 (i.e., decimal 48) + // 'R' is 0x52 (i.e., decimal 82) + // '\r` is 0xd (i.e., decimal 13) + + for (;; count++) { + SemaphoreDown(&rdr->sem); + + int bit = GPIO_GetPin(rdr->data_in); + + // PRULOG_1u32(INFO, "ui1203 read bit 0x%x", bit); + byte = (byte >> 1) | (bit << 9); + + int32_t data = bitsToAscii(byte); + + // PRULOG_2u32(INFO, "ui1203 read byte 0x%x %u", byte, parity); + + // When parity matches and the start and stop bits are correct. + if (data >= 0) { + // output a byte + PRULOG_1u32(INFO, "ui1203 byte 0x%x", data); + + if (position != 0 && count > 10) { + // PRULOG_1u32(INFO, "ui1203 unused bits: %u", count); + break; + } + position++; + count = 0; + byte = 0; + } + } + } + + // PWM_Disable(); + + SleepUntil32(&clock, 10 * TIME_SECOND); + } +} + +SUPRUGLUE_DEFINE_THREAD(ui1203reader, 256); +SUPRUGLUE_DEFINE_THREAD(ui1203writer, 256); + +void UI1203_Init_Reader(UI1203_Reader *rd, gpio_pin data_pin) { + SemaphoreInit(&rd->sem); + rd->data_in = data_pin; + + Args args; // @@@ + args.ptr = (const char *)rd; + + InterruptHandlerInit(SYSEVT_TPCC_INT_PEND_PO1, readerHandler, args); + + Create(&ui1203reader.thread, readerRunner, args, "ui1203reader", sizeof(ui1203reader.space)); +} + +void writerHandler(Args args) { + // Called after rising edge of clock, produces one bit via GPIO. + UI1203_Writer *wr = (UI1203_Writer *)args.ptr; + SemaphoreUp(&wr->sem); + CAP_ClearInterrupt(); +} + +void writerRunner(ThreadID tid, Args args) { + UI1203_Writer *wr = (UI1203_Writer *)args.ptr; + + while (1) { + + const char *p = "R"; + + for (; *p != 0; p++) { + + int32_t d10 = asciiToBits(*p); + + PRULOG_1u32(INFO, "write word is 0x%x", d10); + + int b; + for (b = 0; b < 10; b++) { + SemaphoreDown(&wr->sem); + + int32_t bit = d10 & 1; + PRULOG_2u32(INFO, "write bit %d is %d", b, bit); + GPIO_SetPin(wr->data_out, bit); + + d10 >>= 1; + } + } + } +} + +void UI1203_Init_Writer(UI1203_Writer *wr, gpio_pin data_pin) { + SemaphoreInit(&wr->sem); + + wr->data_out = data_pin; + + Args args; // @@@ + args.ptr = (const char *)wr; + + InterruptHandlerInit(SYSEVT_PR1_PRU_ECAP_INTR_REQ, writerHandler, args); + + Create(&ui1203writer.thread, writerRunner, args, "ui1203writer", sizeof(ui1203writer.space)); +} + +// Bits: +// 0: start +// 1-7: data (LSB first) +// 8: parity +// 9: stop + +int32_t asciiToBits(int32_t c) { + int32_t ci = (uint32_t)c; + int32_t d0 = ci << 1; + int32_t x1 = (d0 >> 4) ^ d0; + int32_t x2 = (x1 >> 2) ^ x1; + int32_t x3 = (x2 >> 1) ^ x2; + int32_t parity = ~x3 & 0x1; + + d0 |= parity << 8; + d0 |= 1 << 9; + return d0; +} + +int32_t bitsToAscii(int32_t bits) { + int32_t x1 = (bits >> 4) ^ bits; + int32_t x2 = (x1 >> 2) ^ x1; + int32_t x3 = (x2 >> 1) ^ x2; + uint16_t parity = (~x3 & 1); + uint16_t calc = (bits & 0x100) >> 8; + + if (parity != calc || (bits & 0x201) != 0x200) { + return -1; + } + + return (bits >> 1) & 0x7f; +} diff --git a/lib/ui1203/ui1203.h b/lib/ui1203/ui1203.h index f9fa896..8028906 100644 --- a/lib/ui1203/ui1203.h +++ b/lib/ui1203/ui1203.h @@ -5,19 +5,38 @@ #define LIB_UI1203_SUPRUGLUE_UI1203_H #include "lib/gpio/gpio.h" +#include "lib/sync/sync.h" #ifdef __cplusplus extern "C" { #endif typedef struct { - gpio_pin clock; - gpio_pin data; + Semaphore sem; + gpio_pin data_in; + + // Clock is configured through ePWM output + } UI1203_Reader; -// void UI1203_Init_Reader(UI1203_Reader *rdr, gpio_pin clock, gpio_pin data); +typedef struct { + Semaphore sem; + gpio_pin data_out; + + // Clock is configured through eCAP input + +} UI1203_Writer; + +// Note! Uses ePWM1 to generate clock. Uses GPIO to read. +void UI1203_Init_Reader(UI1203_Reader *rdr, gpio_pin data); + +// Note! Uses PRU-eCAP0 to receive clock. Uses GPIO to write. +void UI1203_Init_Writer(UI1203_Writer *wr, gpio_pin data); + +// Internal. -// void UI1203_Run_Reader(UI1203_Reader *rdr); +int32_t asciiToBits(int32_t c); +int32_t bitsToAscii(int32_t b); #ifdef __cplusplus } diff --git a/lib/ui1203/ui1203_test.cc b/lib/ui1203/ui1203_test.cc index 70cf02d..8468bd2 100644 --- a/lib/ui1203/ui1203_test.cc +++ b/lib/ui1203/ui1203_test.cc @@ -1,15 +1,14 @@ // Copyright Joshua MacDonald // SPDX-License-Identifier: MIT -#include "supruglue/pinmap-arch.h" -#include "supruglue/test32/gpio.h" -#include "supruglue/test32/soc.h" #include "ui1203.h" #include "gtest/gtest.h" -// TEST(Ui1203Test, Output) { -// test_system *soc = new test_system; +TEST(Ui1203Test, Bits) { + for (unsigned char c = 0; c < 128; c++) { + int32_t bits = asciiToBits(c); + uint8_t ascii = bitsToAscii(bits); -// UI1203_Reader rdr; -// UI1203_Init_Reader(&rdr, GPIO_PIN(soc, P8_3), GPIO_PIN(soc, P9_25)); -// } + EXPECT_EQ(c, ascii); + } +} diff --git a/local.sh b/local.sh index 7e31bca..6201f67 100755 --- a/local.sh +++ b/local.sh @@ -1,7 +1,7 @@ #!/bin/sh PRU=pru0 -EXAMPLE=pwm_outin +EXAMPLE=${EXAMPLE:-pwm_outin} REMOTEPROC=/sys/class/remoteproc/remoteproc1 REMOTE=./remote.sh diff --git a/remote.sh b/remote.sh index eafb185..f7d482e 100755 --- a/remote.sh +++ b/remote.sh @@ -10,8 +10,8 @@ PID="" #OUT_GPIOs="gpio17 gpio115" #OUT_GPIOs=${ALL_GPIOs} -OUT_GPIOs="gpio49" # P9.23 -IN_GPIOs="gpio117 gpio60" # P9.25 P9.12 +# OUT_GPIOs="gpio49 gpio44 gpio45" # P9.23 P8.11 P8.12 +# IN_GPIOs="gpio117 gpio60" # P9.25 P9.12 LEDs="beaglebone:green:usr0 beaglebone:green:usr1 beaglebone:green:usr2 beaglebone:green:usr3" @@ -26,19 +26,25 @@ configPins() { for led in ${LEDs}; do echo none > /sys/class/leds/${led}/trigger done - echo "Configuring GPIO pins" - for gpio in ${OUT_GPIOs}; do - echo out > /sys/class/gpio/${gpio}/direction - done - for gpio in ${IN_GPIOs}; do - echo in > /sys/class/gpio/${gpio}/direction - done + # echo "Configuring GPIO pins" + # for gpio in ${OUT_GPIOs}; do + # echo out > /sys/class/gpio/${gpio}/direction + # done + # for gpio in ${IN_GPIOs}; do + # echo in > /sys/class/gpio/${gpio}/direction + # done } -configPins +#configPins # Works! -config-pin P9_14 pwm +#config-pin P9_14 pwm + +# Not sure how to get ecap0 in +#config-pin P9_92 pruin +#config-pin P9_42 pru_ecap + +#config-pin P9_92 pruin # echo "Stopping ..." diff --git a/save/cap/am335x/.#cap-am335x.c b/save/cap/am335x/.#cap-am335x.c deleted file mode 120000 index 37c8d2f..0000000 --- a/save/cap/am335x/.#cap-am335x.c +++ /dev/null @@ -1 +0,0 @@ -josh.macdonald@Joshuas-MacBook-Pro.local.35299 \ No newline at end of file diff --git a/save/cap/am335x/BUILD b/save/cap/am335x/BUILD index 54ab2a4..0d4ef76 100644 --- a/save/cap/am335x/BUILD +++ b/save/cap/am335x/BUILD @@ -3,12 +3,12 @@ package(default_visibility = ["//visibility:public"]) cc_library( name = "am335x", - hdrs = [ - "cap-am335x.h", - ], srcs = [ "cap-am335x.c", ], + hdrs = [ + "cap-am335x.h", + ], deps = [ "//lib/cap:defs", "//tools/toolchain/am335x", diff --git a/tools/cmd/supructl/BUILD b/tools/cmd/supructl/BUILD index 1ef4f4c..1d68dd0 100644 --- a/tools/cmd/supructl/BUILD +++ b/tools/cmd/supructl/BUILD @@ -7,7 +7,11 @@ go_library( importpath = "github.com/jmacd/supruglue/tools/cmd/supructl", visibility = ["//visibility:private"], deps = [ + "//arch/am335x", + "//tools/internal/arch", + "//tools/internal/csv", "//tools/internal/firmware", + "//tools/internal/memorymap", "//tools/internal/remoteproc", "//tools/internal/rpmsghost", "@com_github_spf13_cobra//:cobra", diff --git a/tools/cmd/supructl/main.go b/tools/cmd/supructl/main.go index 8eab949..f6dc98d 100644 --- a/tools/cmd/supructl/main.go +++ b/tools/cmd/supructl/main.go @@ -3,7 +3,14 @@ package main import ( "fmt" "os" + "strconv" + "strings" + "syscall" + "unsafe" + "github.com/jmacd/supruglue/arch/am335x" + "github.com/jmacd/supruglue/tools/internal/arch" + "github.com/jmacd/supruglue/tools/internal/csv" "github.com/jmacd/supruglue/tools/internal/firmware" "github.com/jmacd/supruglue/tools/internal/remoteproc" "github.com/jmacd/supruglue/tools/internal/rpmsghost" @@ -28,6 +35,7 @@ func init() { rootCmd.AddCommand(startCmd) rootCmd.AddCommand(stopCmd) rootCmd.AddCommand(rodataCmd) + rootCmd.AddCommand(dumpCmd) } var journalCmd = &cobra.Command{ @@ -57,6 +65,13 @@ var rodataCmd = &cobra.Command{ RunE: runRodata, } +var dumpCmd = &cobra.Command{ + Use: "dump", + Short: "Dump a register file", + Args: cobra.ExactArgs(1), + RunE: runDump, +} + func main() { err := rootCmd.Execute() if err != nil { @@ -147,3 +162,135 @@ func runRodata(cmd *cobra.Command, args []string) error { fw.ELF.Show() return nil } + +func abbrevHex(in string) uint32 { + // remove trailing "h" + u, err := strconv.ParseUint(in[:len(in)-1], 16, 32) + if err != nil { + panic(err) + } + return uint32(u) +} + +func fromNum(in string) uint32 { + u, err := strconv.ParseUint(in, 0, 32) + if err != nil { + panic(err) + } + return uint32(u) +} + +func mmap(file *os.File, addr uint32, size int) ([]byte, error) { + return syscall.Mmap( + int(file.Fd()), + int64(addr), + size, + syscall.PROT_READ|syscall.PROT_WRITE, + syscall.MAP_SHARED, + ) +} + +func munmap(data []byte) error { + return syscall.Munmap(data) +} + +func runDump(cmd *cobra.Command, args []string) error { + const listing = "am335x-map.csv" + + dump := args[0] + + fs := am335x.FS + entries, err := fs.ReadDir(".") + if err != nil { + return err + } + + modmap, err := fs.Open(listing) + if err != nil { + return err + } + + allMods, err := csv.Read[arch.Module]("am335x-map.csv", modmap) + if err != nil { + return err + } + + layouts := map[string][]arch.Register{} + + for _, ent := range entries { + if ent.Name() == "am335x-map.csv" { + continue + } + bn := strings.TrimSuffix(ent.Name(), ".csv") + ef, err := fs.Open(ent.Name()) + if err != nil { + return err + } + regs, err := csv.Read[arch.Register](bn, ef) + if err != nil { + return err + } + layouts[bn] = regs + } + + var dumpMod arch.Module + for _, mod := range allMods { + _, ok := layouts[mod.Layout] + if !ok { + return fmt.Errorf("missing layout definition: %q", mod.Layout) + } + + if mod.Module == dump { + dumpMod = mod + } + } + if dumpMod.Layout == "" { + return fmt.Errorf("module not found: %q", dump) + } + + layout := layouts[dumpMod.Layout] + base := fromNum(dumpMod.Base) + + mem, err := os.OpenFile("/dev/mem", os.O_RDWR|os.O_SYNC, 0) + if err != nil { + return fmt.Errorf("open /dev/mem: %w", err) + } + + var ptr []byte + var paddr uint32 + + defer mem.Close() + defer munmap(ptr) + + for _, reg := range layout { + + const pgsz uint32 = 4096 + + addr := base + abbrevHex(reg.Offset) + page := addr & ^(pgsz - 1) + pgoff := addr & (pgsz - 1) + + if page != paddr { + if ptr != nil { + munmap(ptr) + ptr = nil + } + paddr = page + ptr, err = mmap(mem, page, int(pgsz)) + if err != nil { + return fmt.Errorf("mmap /dev/mem: %w", err) + } + } + + var val any + switch fromNum(dumpMod.Unit) { + case 2: + val = (*(*[2048]uint16)(unsafe.Pointer(&ptr[0])))[pgoff/2] + case 4: + val = (*(*[1024]uint32)(unsafe.Pointer(&ptr[0])))[pgoff/4] + } + fmt.Printf("@%x: %s = %x\n", addr, reg.Name, val) + } + + return nil +} diff --git a/tools/internal/arch/BUILD b/tools/internal/arch/BUILD index d162156..39d99c3 100644 --- a/tools/internal/arch/BUILD +++ b/tools/internal/arch/BUILD @@ -5,7 +5,9 @@ go_library( name = "arch", srcs = [ "irq.go", + "module.go", "pin.go", + "register.go", "sysevt.go", ], importpath = "github.com/jmacd/supruglue/tools/internal/arch", diff --git a/tools/internal/arch/module.go b/tools/internal/arch/module.go new file mode 100644 index 0000000..85d6334 --- /dev/null +++ b/tools/internal/arch/module.go @@ -0,0 +1,12 @@ +package arch + +type Module struct { + Module string + Base string + Unit string + Layout string +} + +func (r Module) Validate() error { + return nil +} diff --git a/tools/internal/arch/register.go b/tools/internal/arch/register.go new file mode 100644 index 0000000..43e46ff --- /dev/null +++ b/tools/internal/arch/register.go @@ -0,0 +1,20 @@ +package arch + +import ( + "fmt" + "strings" +) + +type Register struct { + Offset string + Name string + Description string +} + +func (r Register) Validate() error { + if !strings.HasSuffix(r.Offset, "h") { + return fmt.Errorf("should have h suffix: %q", r.Offset) + } + + return nil +} diff --git a/tools/internal/memorymap/BUILD b/tools/internal/memorymap/BUILD new file mode 100644 index 0000000..02ca96a --- /dev/null +++ b/tools/internal/memorymap/BUILD @@ -0,0 +1,8 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "memorymap", + srcs = ["memorymap.go"], + importpath = "github.com/jmacd/supruglue/tools/internal/memorymap", + visibility = ["//tools:__subpackages__"], +) diff --git a/tools/internal/memorymap/am335x/BUILD b/tools/internal/memorymap/am335x/BUILD new file mode 100644 index 0000000..9ca5fad --- /dev/null +++ b/tools/internal/memorymap/am335x/BUILD @@ -0,0 +1,8 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "am335x", + srcs = ["module.go"], + importpath = "github.com/jmacd/supruglue/tools/internal/memorymap/am335x", + visibility = ["//tools:__subpackages__"], +) diff --git a/tools/internal/memorymap/am335x/module.go b/tools/internal/memorymap/am335x/module.go new file mode 100644 index 0000000..356b4e5 --- /dev/null +++ b/tools/internal/memorymap/am335x/module.go @@ -0,0 +1,11 @@ +package am335x + +// import "github.com/jmacd/supruglue/tools/internal/memorymap" + +// var Modules = []memorymap.Module{ +// { +// "ePWM1", 0x48302200, memorymap.MakeRegisters( +// memorymap. +// ), +// }, +// } diff --git a/tools/internal/memorymap/memorymap.go b/tools/internal/memorymap/memorymap.go new file mode 100644 index 0000000..8fc0f8b --- /dev/null +++ b/tools/internal/memorymap/memorymap.go @@ -0,0 +1,45 @@ +package memorymap + +type Module struct { + Name string + Base uint32 + Registers []Register +} + +type Register interface { + Name() string + Offset() uint32 + Size() uint8 +} + +type RegisterBase struct { + name string + offset uint32 +} + +type Register32 struct { + RegisterBase +} + +type Register16 struct { + RegisterBase +} + +var _ Register = Register32{} +var _ Register = Register16{} + +func (r RegisterBase) Name() string { + return r.name +} + +func (r RegisterBase) Offset() uint32 { + return r.offset +} + +func (r Register16) Size() uint8 { + return 2 +} + +func (r Register32) Size() uint8 { + return 4 +} diff --git a/tools/internal/rpmsghost/rpmsghost.go b/tools/internal/rpmsghost/rpmsghost.go index d422aee..e30e11d 100644 --- a/tools/internal/rpmsghost/rpmsghost.go +++ b/tools/internal/rpmsghost/rpmsghost.go @@ -16,6 +16,8 @@ import ( const logEntrySize = 36 +const statsInterval = time.Second * 24 * 60 * 60 + type RPMsgDevice struct { file *os.File } @@ -58,7 +60,8 @@ func (host *Host) Run() error { fmt.Println("rpmsg: channel open") go func() { - t := time.NewTicker(time.Second * 5) + // @@@ config + t := time.NewTicker(statsInterval) defer t.Stop() for { select {