Add files via upload
This commit is contained in:
@@ -0,0 +1,255 @@
|
||||
#MicroXplorer Configuration settings - do not modify
|
||||
CAD.formats=
|
||||
CAD.pinconfig=
|
||||
CAD.provider=
|
||||
File.Version=6
|
||||
GPIO.groupedBy=Group By Peripherals
|
||||
I2C1.IPParameters=Timing
|
||||
I2C1.Timing=0x00707CBB
|
||||
KeepUserPlacement=false
|
||||
Mcu.CPN=STM32F746ZGT6
|
||||
Mcu.Family=STM32F7
|
||||
Mcu.IP0=CORTEX_M7
|
||||
Mcu.IP1=I2C1
|
||||
Mcu.IP2=NVIC
|
||||
Mcu.IP3=RCC
|
||||
Mcu.IP4=SPI1
|
||||
Mcu.IP5=SYS
|
||||
Mcu.IP6=TIM1
|
||||
Mcu.IP7=USART2
|
||||
Mcu.IPNb=8
|
||||
Mcu.Name=STM32F746ZGTx
|
||||
Mcu.Package=LQFP144
|
||||
Mcu.Pin0=PC14/OSC32_IN
|
||||
Mcu.Pin1=PC15/OSC32_OUT
|
||||
Mcu.Pin10=PA5
|
||||
Mcu.Pin11=PA6
|
||||
Mcu.Pin12=PA7
|
||||
Mcu.Pin13=PC4
|
||||
Mcu.Pin14=PC5
|
||||
Mcu.Pin15=PB14
|
||||
Mcu.Pin16=PB15
|
||||
Mcu.Pin17=PD10
|
||||
Mcu.Pin18=PD11
|
||||
Mcu.Pin19=PD12
|
||||
Mcu.Pin2=PH0/OSC_IN
|
||||
Mcu.Pin20=PD13
|
||||
Mcu.Pin21=PC6
|
||||
Mcu.Pin22=PC7
|
||||
Mcu.Pin23=PA8
|
||||
Mcu.Pin24=PA9
|
||||
Mcu.Pin25=PA10
|
||||
Mcu.Pin26=PA11
|
||||
Mcu.Pin27=PA13
|
||||
Mcu.Pin28=PA14
|
||||
Mcu.Pin29=PD0
|
||||
Mcu.Pin3=PH1/OSC_OUT
|
||||
Mcu.Pin30=PD1
|
||||
Mcu.Pin31=PD2
|
||||
Mcu.Pin32=PD3
|
||||
Mcu.Pin33=PB4
|
||||
Mcu.Pin34=PB5
|
||||
Mcu.Pin35=PB6
|
||||
Mcu.Pin36=PB7
|
||||
Mcu.Pin37=VP_SYS_VS_Systick
|
||||
Mcu.Pin38=VP_TIM1_VS_ClockSourceINT
|
||||
Mcu.Pin4=PC0
|
||||
Mcu.Pin5=PC1
|
||||
Mcu.Pin6=PC2
|
||||
Mcu.Pin7=PC3
|
||||
Mcu.Pin8=PA2
|
||||
Mcu.Pin9=PA3
|
||||
Mcu.PinsNb=39
|
||||
Mcu.ThirdPartyNb=0
|
||||
Mcu.UserConstants=
|
||||
Mcu.UserName=STM32F746ZGTx
|
||||
MxCube.Version=6.8.1
|
||||
MxDb.Version=DB.6.0.81
|
||||
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||
NVIC.ForceEnableDMAVector=true
|
||||
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||
NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
||||
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:false
|
||||
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||
PA10.Locked=true
|
||||
PA10.Signal=GPIO_Output
|
||||
PA11.Locked=true
|
||||
PA11.Signal=GPIO_Output
|
||||
PA13.Mode=Serial_Wire
|
||||
PA13.Signal=SYS_JTMS-SWDIO
|
||||
PA14.Mode=Serial_Wire
|
||||
PA14.Signal=SYS_JTCK-SWCLK
|
||||
PA2.Mode=Asynchronous
|
||||
PA2.Signal=USART2_TX
|
||||
PA3.Mode=Asynchronous
|
||||
PA3.Signal=USART2_RX
|
||||
PA5.Mode=Full_Duplex_Master
|
||||
PA5.Signal=SPI1_SCK
|
||||
PA6.Mode=Full_Duplex_Master
|
||||
PA6.Signal=SPI1_MISO
|
||||
PA7.Mode=Full_Duplex_Master
|
||||
PA7.Signal=SPI1_MOSI
|
||||
PA8.Locked=true
|
||||
PA8.Signal=GPIO_Output
|
||||
PA9.Locked=true
|
||||
PA9.Signal=GPIO_Output
|
||||
PB14.Locked=true
|
||||
PB14.Signal=GPIO_Output
|
||||
PB15.Locked=true
|
||||
PB15.Signal=GPIO_Output
|
||||
PB4.Locked=true
|
||||
PB4.Signal=GPIO_Output
|
||||
PB5.Locked=true
|
||||
PB5.Signal=GPIO_Output
|
||||
PB6.Mode=I2C
|
||||
PB6.Signal=I2C1_SCL
|
||||
PB7.Mode=I2C
|
||||
PB7.Signal=I2C1_SDA
|
||||
PC0.Locked=true
|
||||
PC0.Signal=GPIO_Input
|
||||
PC1.Locked=true
|
||||
PC1.Signal=GPIO_Input
|
||||
PC14/OSC32_IN.Mode=LSE-External-Oscillator
|
||||
PC14/OSC32_IN.Signal=RCC_OSC32_IN
|
||||
PC15/OSC32_OUT.Mode=LSE-External-Oscillator
|
||||
PC15/OSC32_OUT.Signal=RCC_OSC32_OUT
|
||||
PC2.Locked=true
|
||||
PC2.Signal=GPIO_Input
|
||||
PC3.Locked=true
|
||||
PC3.Signal=GPIO_Input
|
||||
PC4.Locked=true
|
||||
PC4.Signal=GPIO_Output
|
||||
PC5.Locked=true
|
||||
PC5.Signal=GPIO_Output
|
||||
PC6.Locked=true
|
||||
PC6.Signal=GPIO_Output
|
||||
PC7.Locked=true
|
||||
PC7.Signal=GPIO_Output
|
||||
PD0.Locked=true
|
||||
PD0.Signal=GPIO_Output
|
||||
PD1.Locked=true
|
||||
PD1.Signal=GPIO_Output
|
||||
PD10.Locked=true
|
||||
PD10.Signal=GPIO_Output
|
||||
PD11.Locked=true
|
||||
PD11.Signal=GPIO_Output
|
||||
PD12.Locked=true
|
||||
PD12.Signal=GPIO_Output
|
||||
PD13.Locked=true
|
||||
PD13.Signal=GPIO_Output
|
||||
PD2.Locked=true
|
||||
PD2.Signal=GPIO_Output
|
||||
PD3.Locked=true
|
||||
PD3.Signal=GPIO_Output
|
||||
PH0/OSC_IN.Mode=HSE-External-Oscillator
|
||||
PH0/OSC_IN.Signal=RCC_OSC_IN
|
||||
PH1/OSC_OUT.Mode=HSE-External-Oscillator
|
||||
PH1/OSC_OUT.Signal=RCC_OSC_OUT
|
||||
PinOutPanel.RotationAngle=0
|
||||
ProjectManager.AskForMigrate=true
|
||||
ProjectManager.BackupPrevious=false
|
||||
ProjectManager.CompilerOptimize=6
|
||||
ProjectManager.ComputerToolchain=false
|
||||
ProjectManager.CoupleFile=false
|
||||
ProjectManager.CustomerFirmwarePackage=
|
||||
ProjectManager.DefaultFWLocation=true
|
||||
ProjectManager.DeletePrevious=true
|
||||
ProjectManager.DeviceId=STM32F746ZGTx
|
||||
ProjectManager.FirmwarePackage=STM32Cube FW_F7 V1.17.2
|
||||
ProjectManager.FreePins=false
|
||||
ProjectManager.HalAssertFull=false
|
||||
ProjectManager.HeapSize=0x200
|
||||
ProjectManager.KeepUserCode=true
|
||||
ProjectManager.LastFirmware=true
|
||||
ProjectManager.LibraryCopy=1
|
||||
ProjectManager.MainLocation=Core/Src
|
||||
ProjectManager.NoMain=false
|
||||
ProjectManager.PreviousToolchain=STM32CubeIDE
|
||||
ProjectManager.ProjectBuild=false
|
||||
ProjectManager.ProjectFileName=RADAR_C_Cpp.ioc
|
||||
ProjectManager.ProjectName=RADAR_C_Cpp
|
||||
ProjectManager.ProjectStructure=
|
||||
ProjectManager.RegisterCallBack=
|
||||
ProjectManager.StackSize=0x400
|
||||
ProjectManager.TargetToolchain=STM32CubeIDE
|
||||
ProjectManager.ToolChainLocation=
|
||||
ProjectManager.UnderRoot=true
|
||||
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_I2C1_Init-I2C1-false-HAL-true,4-MX_SPI1_Init-SPI1-false-HAL-true,5-MX_TIM1_Init-TIM1-false-HAL-true,6-MX_USART2_UART_Init-USART2-false-HAL-true,0-MX_CORTEX_M7_Init-CORTEX_M7-false-HAL-true
|
||||
RCC.AHBFreq_Value=64000000
|
||||
RCC.APB1CLKDivider=RCC_HCLK_DIV2
|
||||
RCC.APB1Freq_Value=32000000
|
||||
RCC.APB1TimFreq_Value=64000000
|
||||
RCC.APB2Freq_Value=64000000
|
||||
RCC.APB2TimFreq_Value=64000000
|
||||
RCC.CECFreq_Value=32786.88524590164
|
||||
RCC.CortexFreq_Value=64000000
|
||||
RCC.EthernetFreq_Value=64000000
|
||||
RCC.FCLKCortexFreq_Value=64000000
|
||||
RCC.FamilyName=M
|
||||
RCC.HCLKFreq_Value=64000000
|
||||
RCC.HSE_VALUE=8000000
|
||||
RCC.HSI_VALUE=16000000
|
||||
RCC.I2C1Freq_Value=32000000
|
||||
RCC.I2C2Freq_Value=32000000
|
||||
RCC.I2C3Freq_Value=32000000
|
||||
RCC.I2C4Freq_Value=32000000
|
||||
RCC.I2SFreq_Value=192000000
|
||||
RCC.IPParameters=AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,CECFreq_Value,CortexFreq_Value,EthernetFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,I2C1Freq_Value,I2C2Freq_Value,I2C3Freq_Value,I2C4Freq_Value,I2SFreq_Value,LCDTFToutputFreq_Value,LPTIM1Freq_Value,LSI_VALUE,MCO2PinFreq_Value,PLLCLKFreq_Value,PLLI2SPCLKFreq_Value,PLLI2SQCLKFreq_Value,PLLI2SRCLKFreq_Value,PLLI2SRoutputFreq_Value,PLLM,PLLN,PLLQCLKFreq_Value,PLLQoutputFreq_Value,PLLSAIPCLKFreq_Value,PLLSAIQCLKFreq_Value,PLLSAIRCLKFreq_Value,PLLSAIoutputFreq_Value,PLLSourceVirtual,RNGFreq_Value,SAI1Freq_Value,SAI2Freq_Value,SDMMCFreq_Value,SPDIFRXFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,UART4Freq_Value,UART5Freq_Value,UART7Freq_Value,UART8Freq_Value,USART1Freq_Value,USART2Freq_Value,USART3Freq_Value,USART6Freq_Value,USBFreq_Value,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VCOSAIOutputFreq_Value
|
||||
RCC.LCDTFToutputFreq_Value=96000000
|
||||
RCC.LPTIM1Freq_Value=32000000
|
||||
RCC.LSI_VALUE=32000
|
||||
RCC.MCO2PinFreq_Value=64000000
|
||||
RCC.PLLCLKFreq_Value=64000000
|
||||
RCC.PLLI2SPCLKFreq_Value=192000000
|
||||
RCC.PLLI2SQCLKFreq_Value=192000000
|
||||
RCC.PLLI2SRCLKFreq_Value=192000000
|
||||
RCC.PLLI2SRoutputFreq_Value=192000000
|
||||
RCC.PLLM=4
|
||||
RCC.PLLN=64
|
||||
RCC.PLLQCLKFreq_Value=64000000
|
||||
RCC.PLLQoutputFreq_Value=64000000
|
||||
RCC.PLLSAIPCLKFreq_Value=192000000
|
||||
RCC.PLLSAIQCLKFreq_Value=192000000
|
||||
RCC.PLLSAIRCLKFreq_Value=192000000
|
||||
RCC.PLLSAIoutputFreq_Value=192000000
|
||||
RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE
|
||||
RCC.RNGFreq_Value=64000000
|
||||
RCC.SAI1Freq_Value=192000000
|
||||
RCC.SAI2Freq_Value=192000000
|
||||
RCC.SDMMCFreq_Value=64000000
|
||||
RCC.SPDIFRXFreq_Value=192000000
|
||||
RCC.SYSCLKFreq_VALUE=64000000
|
||||
RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
|
||||
RCC.UART4Freq_Value=32000000
|
||||
RCC.UART5Freq_Value=32000000
|
||||
RCC.UART7Freq_Value=32000000
|
||||
RCC.UART8Freq_Value=32000000
|
||||
RCC.USART1Freq_Value=64000000
|
||||
RCC.USART2Freq_Value=32000000
|
||||
RCC.USART3Freq_Value=32000000
|
||||
RCC.USART6Freq_Value=64000000
|
||||
RCC.USBFreq_Value=64000000
|
||||
RCC.VCOI2SOutputFreq_Value=384000000
|
||||
RCC.VCOInputFreq_Value=2000000
|
||||
RCC.VCOOutputFreq_Value=128000000
|
||||
RCC.VCOSAIOutputFreq_Value=384000000
|
||||
SPI1.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_16
|
||||
SPI1.CalculateBaudRate=4.0 MBits/s
|
||||
SPI1.DataSize=SPI_DATASIZE_8BIT
|
||||
SPI1.Direction=SPI_DIRECTION_2LINES
|
||||
SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,BaudRatePrescaler,DataSize
|
||||
SPI1.Mode=SPI_MODE_MASTER
|
||||
SPI1.VirtualType=VM_MASTER
|
||||
USART2.IPParameters=VirtualMode-Asynchronous
|
||||
USART2.VirtualMode-Asynchronous=VM_ASYNC
|
||||
VP_SYS_VS_Systick.Mode=SysTick
|
||||
VP_SYS_VS_Systick.Signal=SYS_VS_Systick
|
||||
VP_TIM1_VS_ClockSourceINT.Mode=Internal
|
||||
VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT
|
||||
board=custom
|
||||
isbadioc=false
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
**
|
||||
** @file : LinkerScript.ld
|
||||
**
|
||||
** @author : Auto-generated by STM32CubeIDE
|
||||
**
|
||||
** @brief : Linker script for STM32F746ZGTx Device from STM32F7 series
|
||||
** 1024Kbytes FLASH
|
||||
** 320Kbytes RAM
|
||||
**
|
||||
** Set heap size, stack size and stack location according
|
||||
** to application requirements.
|
||||
**
|
||||
** Set memory bank area and size if external memory is used
|
||||
**
|
||||
** Target : STMicroelectronics STM32
|
||||
**
|
||||
** Distribution: The file is distributed as is, without any warranty
|
||||
** of any kind.
|
||||
**
|
||||
******************************************************************************
|
||||
** @attention
|
||||
**
|
||||
** Copyright (c) 2025 STMicroelectronics.
|
||||
** All rights reserved.
|
||||
**
|
||||
** This software is licensed under terms that can be found in the LICENSE file
|
||||
** in the root directory of this software component.
|
||||
** If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
**
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Entry Point */
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
/* Highest address of the user mode stack */
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
|
||||
|
||||
_Min_Heap_Size = 0x200; /* required amount of heap */
|
||||
_Min_Stack_Size = 0x400; /* required amount of stack */
|
||||
|
||||
/* Memories definition */
|
||||
MEMORY
|
||||
{
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K
|
||||
}
|
||||
|
||||
/* Sections */
|
||||
SECTIONS
|
||||
{
|
||||
/* The startup code into "FLASH" Rom type memory */
|
||||
.isr_vector :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.isr_vector)) /* Startup code */
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
/* The program code and other data into "FLASH" Rom type memory */
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.text) /* .text sections (code) */
|
||||
*(.text*) /* .text* sections (code) */
|
||||
*(.glue_7) /* glue arm to thumb code */
|
||||
*(.glue_7t) /* glue thumb to arm code */
|
||||
*(.eh_frame)
|
||||
|
||||
KEEP (*(.init))
|
||||
KEEP (*(.fini))
|
||||
|
||||
. = ALIGN(4);
|
||||
_etext = .; /* define a global symbols at end of code */
|
||||
} >FLASH
|
||||
|
||||
/* Constant data into "FLASH" Rom type memory */
|
||||
.rodata :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.rodata) /* .rodata sections (constants, strings, etc.) */
|
||||
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.ARM.extab : {
|
||||
. = ALIGN(4);
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.ARM : {
|
||||
. = ALIGN(4);
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx*)
|
||||
__exidx_end = .;
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array*))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.init_array :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array*))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
KEEP (*(.fini_array*))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
/* Used by the startup to initialize data */
|
||||
_sidata = LOADADDR(.data);
|
||||
|
||||
/* Initialized data sections into "RAM" Ram type memory */
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sdata = .; /* create a global symbol at data start */
|
||||
*(.data) /* .data sections */
|
||||
*(.data*) /* .data* sections */
|
||||
*(.RamFunc) /* .RamFunc sections */
|
||||
*(.RamFunc*) /* .RamFunc* sections */
|
||||
|
||||
. = ALIGN(4);
|
||||
_edata = .; /* define a global symbol at data end */
|
||||
|
||||
} >RAM AT> FLASH
|
||||
|
||||
/* Uninitialized data section into "RAM" Ram type memory */
|
||||
. = ALIGN(4);
|
||||
.bss :
|
||||
{
|
||||
/* This is used by the startup in order to initialize the .bss section */
|
||||
_sbss = .; /* define a global symbol at bss start */
|
||||
__bss_start__ = _sbss;
|
||||
*(.bss)
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
|
||||
. = ALIGN(4);
|
||||
_ebss = .; /* define a global symbol at bss end */
|
||||
__bss_end__ = _ebss;
|
||||
} >RAM
|
||||
|
||||
/* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */
|
||||
._user_heap_stack :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
PROVIDE ( end = . );
|
||||
PROVIDE ( _end = . );
|
||||
. = . + _Min_Heap_Size;
|
||||
. = . + _Min_Stack_Size;
|
||||
. = ALIGN(8);
|
||||
} >RAM
|
||||
|
||||
/* Remove information from the compiler libraries */
|
||||
/DISCARD/ :
|
||||
{
|
||||
libc.a ( * )
|
||||
libm.a ( * )
|
||||
libgcc.a ( * )
|
||||
}
|
||||
|
||||
.ARM.attributes 0 : { *(.ARM.attributes) }
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
**
|
||||
** @file : LinkerScript.ld (debug in RAM dedicated)
|
||||
**
|
||||
** @author : Auto-generated by STM32CubeIDE
|
||||
**
|
||||
** @brief : Linker script for STM32F746ZGTx Device from STM32F7 series
|
||||
** 1024Kbytes FLASH
|
||||
** 320Kbytes RAM
|
||||
**
|
||||
** Set heap size, stack size and stack location according
|
||||
** to application requirements.
|
||||
**
|
||||
** Set memory bank area and size if external memory is used
|
||||
**
|
||||
** Target : STMicroelectronics STM32
|
||||
**
|
||||
** Distribution: The file is distributed as is, without any warranty
|
||||
** of any kind.
|
||||
**
|
||||
******************************************************************************
|
||||
** @attention
|
||||
**
|
||||
** Copyright (c) 2025 STMicroelectronics.
|
||||
** All rights reserved.
|
||||
**
|
||||
** This software is licensed under terms that can be found in the LICENSE file
|
||||
** in the root directory of this software component.
|
||||
** If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
**
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Entry Point */
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
/* Highest address of the user mode stack */
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
|
||||
|
||||
_Min_Heap_Size = 0x200; /* required amount of heap */
|
||||
_Min_Stack_Size = 0x400; /* required amount of stack */
|
||||
|
||||
/* Memories definition */
|
||||
MEMORY
|
||||
{
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K
|
||||
}
|
||||
|
||||
/* Sections */
|
||||
SECTIONS
|
||||
{
|
||||
/* The startup code into "RAM" Ram type memory */
|
||||
.isr_vector :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.isr_vector)) /* Startup code */
|
||||
. = ALIGN(4);
|
||||
} >RAM
|
||||
|
||||
/* The program code and other data into "RAM" Ram type memory */
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.text) /* .text sections (code) */
|
||||
*(.text*) /* .text* sections (code) */
|
||||
*(.glue_7) /* glue arm to thumb code */
|
||||
*(.glue_7t) /* glue thumb to arm code */
|
||||
*(.eh_frame)
|
||||
*(.RamFunc) /* .RamFunc sections */
|
||||
*(.RamFunc*) /* .RamFunc* sections */
|
||||
|
||||
KEEP (*(.init))
|
||||
KEEP (*(.fini))
|
||||
|
||||
. = ALIGN(4);
|
||||
_etext = .; /* define a global symbols at end of code */
|
||||
} >RAM
|
||||
|
||||
/* Constant data into "RAM" Ram type memory */
|
||||
.rodata :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.rodata) /* .rodata sections (constants, strings, etc.) */
|
||||
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
|
||||
. = ALIGN(4);
|
||||
} >RAM
|
||||
|
||||
.ARM.extab : {
|
||||
. = ALIGN(4);
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
. = ALIGN(4);
|
||||
} >RAM
|
||||
|
||||
.ARM : {
|
||||
. = ALIGN(4);
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx*)
|
||||
__exidx_end = .;
|
||||
. = ALIGN(4);
|
||||
} >RAM
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array*))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
. = ALIGN(4);
|
||||
} >RAM
|
||||
|
||||
.init_array :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array*))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
. = ALIGN(4);
|
||||
} >RAM
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
KEEP (*(.fini_array*))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
. = ALIGN(4);
|
||||
} >RAM
|
||||
|
||||
/* Used by the startup to initialize data */
|
||||
_sidata = LOADADDR(.data);
|
||||
|
||||
/* Initialized data sections into "RAM" Ram type memory */
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sdata = .; /* create a global symbol at data start */
|
||||
*(.data) /* .data sections */
|
||||
*(.data*) /* .data* sections */
|
||||
|
||||
. = ALIGN(4);
|
||||
_edata = .; /* define a global symbol at data end */
|
||||
|
||||
} >RAM
|
||||
|
||||
/* Uninitialized data section into "RAM" Ram type memory */
|
||||
. = ALIGN(4);
|
||||
.bss :
|
||||
{
|
||||
/* This is used by the startup in order to initialize the .bss section */
|
||||
_sbss = .; /* define a global symbol at bss start */
|
||||
__bss_start__ = _sbss;
|
||||
*(.bss)
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
|
||||
. = ALIGN(4);
|
||||
_ebss = .; /* define a global symbol at bss end */
|
||||
__bss_end__ = _ebss;
|
||||
} >RAM
|
||||
|
||||
/* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */
|
||||
._user_heap_stack :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
PROVIDE ( end = . );
|
||||
PROVIDE ( _end = . );
|
||||
. = . + _Min_Heap_Size;
|
||||
. = . + _Min_Stack_Size;
|
||||
. = ALIGN(8);
|
||||
} >RAM
|
||||
|
||||
/* Remove information from the compiler libraries */
|
||||
/DISCARD/ :
|
||||
{
|
||||
libc.a ( * )
|
||||
libm.a ( * )
|
||||
libgcc.a ( * )
|
||||
}
|
||||
|
||||
.ARM.attributes 0 : { *(.ARM.attributes) }
|
||||
}
|
||||
@@ -0,0 +1,693 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 Jimmy Pentz
|
||||
*
|
||||
* Reach me at: github.com/jgpentz, jpentz1(at)gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sells
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
/* ADAR1000 4-Channel, X Band and Ku Band Beamformer */
|
||||
// ----------------------------------------------------------------------------
|
||||
// Includes
|
||||
// ----------------------------------------------------------------------------
|
||||
#include "main.h"
|
||||
#include "stm32f7xx_hal.h"
|
||||
#include "stm32f7xx_hal_spi.h"
|
||||
#include "stm32f7xx_hal_gpio.h"
|
||||
#include "adar1000.h"
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Preprocessor Definitions and Constants
|
||||
// ----------------------------------------------------------------------------
|
||||
// VM_GAIN is 15 dB of gain in 128 steps. ~0.12 dB per step.
|
||||
// A 15 dB attenuator can be applied on top of these values.
|
||||
const uint8_t VM_GAIN[128] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
|
||||
};
|
||||
|
||||
// VM_I and VM_Q are the settings for the vector modulator. 128 steps in 360 degrees. ~2.813 degrees per step.
|
||||
const uint8_t VM_I[128] = {
|
||||
0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3E, 0x3E, 0x3D, 0x3D, 0x3C, 0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37,
|
||||
0x36, 0x35, 0x34, 0x33, 0x32, 0x30, 0x2F, 0x2E, 0x2C, 0x2B, 0x2A, 0x28, 0x27, 0x25, 0x24, 0x22,
|
||||
0x21, 0x01, 0x03, 0x04, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0D, 0x0E, 0x0F, 0x11, 0x12, 0x13, 0x14,
|
||||
0x16, 0x17, 0x18, 0x19, 0x19, 0x1A, 0x1B, 0x1C, 0x1C, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F,
|
||||
0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1E, 0x1D, 0x1D, 0x1C, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17,
|
||||
0x16, 0x15, 0x14, 0x13, 0x12, 0x10, 0x0F, 0x0E, 0x0C, 0x0B, 0x0A, 0x08, 0x07, 0x05, 0x04, 0x02,
|
||||
0x01, 0x21, 0x23, 0x24, 0x26, 0x27, 0x28, 0x2A, 0x2B, 0x2D, 0x2E, 0x2F, 0x31, 0x32, 0x33, 0x34,
|
||||
0x36, 0x37, 0x38, 0x39, 0x39, 0x3A, 0x3B, 0x3C, 0x3C, 0x3D, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F,
|
||||
};
|
||||
|
||||
const uint8_t VM_Q[128] = {
|
||||
0x20, 0x21, 0x23, 0x24, 0x26, 0x27, 0x28, 0x2A, 0x2B, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x33, 0x34,
|
||||
0x35, 0x36, 0x37, 0x38, 0x38, 0x39, 0x3A, 0x3A, 0x3B, 0x3C, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D, 0x3D,
|
||||
0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3C, 0x3C, 0x3C, 0x3B, 0x3A, 0x3A, 0x39, 0x38, 0x38, 0x37, 0x36,
|
||||
0x35, 0x34, 0x33, 0x31, 0x30, 0x2F, 0x2E, 0x2D, 0x2B, 0x2A, 0x28, 0x27, 0x26, 0x24, 0x23, 0x21,
|
||||
0x20, 0x01, 0x03, 0x04, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x13, 0x14,
|
||||
0x15, 0x16, 0x17, 0x18, 0x18, 0x19, 0x1A, 0x1A, 0x1B, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1D, 0x1D,
|
||||
0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1C, 0x1C, 0x1C, 0x1B, 0x1A, 0x1A, 0x19, 0x18, 0x18, 0x17, 0x16,
|
||||
0x15, 0x14, 0x13, 0x11, 0x10, 0x0F, 0x0E, 0x0D, 0x0B, 0x0A, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01,
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Function Definitions
|
||||
// ----------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief Initialize the ADC on the ADAR by setting the ADC with a 2 MHz clk,
|
||||
* and then enable it.
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
* @param broadcast Send the message as a broadcast to all ADARs in the SPI chain
|
||||
* if this set to BROADCAST_ON.
|
||||
*
|
||||
* @warning This is setup to only read temperature sensor data, not the power detectors.
|
||||
*/
|
||||
void Adar_AdcInit(const AdarDevice * p_adar, uint8_t broadcast)
|
||||
{
|
||||
uint8_t data;
|
||||
|
||||
data = ADAR1000_ADC_2MHZ_CLK | ADAR1000_ADC_EN;
|
||||
|
||||
Adar_Write(p_adar, REG_ADC_CONTROL, data, broadcast);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read a byte of data from the ADAR.
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
* @param broadcast Send the message as a broadcast to all ADARs in the SPI chain
|
||||
* if this set to BROADCAST_ON.
|
||||
*
|
||||
* @return Returns a byte of data that has been converted from the temperature sensor.
|
||||
*
|
||||
* @warning This is setup to only read temperature sensor data, not the power detectors.
|
||||
*/
|
||||
uint8_t Adar_AdcRead(const AdarDevice * p_adar, uint8_t broadcast)
|
||||
{
|
||||
uint8_t data;
|
||||
|
||||
// Start the ADC conversion
|
||||
Adar_Write(p_adar, REG_ADC_CONTROL, ADAR1000_ADC_ST_CONV, broadcast);
|
||||
|
||||
// This is blocking for now... wait until data is converted, then read it
|
||||
while (!(Adar_Read(p_adar, REG_ADC_CONTROL) & 0x01))
|
||||
{
|
||||
}
|
||||
|
||||
data = Adar_Read(p_adar, REG_ADC_OUT);
|
||||
|
||||
return(data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Requests the device info from a specific ADAR and stores it in the
|
||||
* provided AdarDeviceInfo struct.
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
* @param info[out] Struct that contains the device info fields.
|
||||
*
|
||||
* @return Returns ADAR_ERROR_NOERROR if information was successfully received and stored in the struct.
|
||||
*/
|
||||
uint8_t Adar_GetDeviceInfo(const AdarDevice * p_adar, AdarDeviceInfo * info)
|
||||
{
|
||||
*((uint8_t *)info) = Adar_Read(p_adar, 0x002);
|
||||
info->chip_type = Adar_Read(p_adar, 0x003);
|
||||
info->product_id = ((uint16_t)Adar_Read(p_adar, 0x004)) << 8;
|
||||
info->product_id |= ((uint16_t)Adar_Read(p_adar, 0x005)) & 0x00ff;
|
||||
info->scratchpad = Adar_Read(p_adar, 0x00A);
|
||||
info->spi_rev = Adar_Read(p_adar, 0x00B);
|
||||
info->vendor_id = ((uint16_t)Adar_Read(p_adar, 0x00C)) << 8;
|
||||
info->vendor_id |= ((uint16_t)Adar_Read(p_adar, 0x00D)) & 0x00ff;
|
||||
info->rev_id = Adar_Read(p_adar, 0x045);
|
||||
|
||||
return(ADAR_ERROR_NOERROR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read the data that is stored in a single ADAR register.
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
* @param mem_addr Memory address of the register you wish to read from.
|
||||
*
|
||||
* @return Returns the byte of data that is stored in the desired register.
|
||||
*
|
||||
* @warning This function will clear ADDR_ASCN bits.
|
||||
* @warning The ADAR does not allow for block reads.
|
||||
*/
|
||||
uint8_t Adar_Read(const AdarDevice * p_adar, uint32_t mem_addr)
|
||||
{
|
||||
uint8_t instruction[3];
|
||||
|
||||
// Set SDO active
|
||||
Adar_Write(p_adar, REG_INTERFACE_CONFIG_A, INTERFACE_CONFIG_A_SDO_ACTIVE, 0);
|
||||
|
||||
instruction[0] = 0x80 | ((p_adar->dev_addr & 0x03) << 5);
|
||||
instruction[0] |= ((0xff00 & mem_addr) >> 8);
|
||||
instruction[1] = (0xff & mem_addr);
|
||||
instruction[2] = 0x00;
|
||||
|
||||
p_adar->Transfer(instruction, p_adar->p_rx_buffer, ADAR1000_RD_SIZE);
|
||||
|
||||
// Set SDO Inactive
|
||||
Adar_Write(p_adar, REG_INTERFACE_CONFIG_A, 0, 0);
|
||||
|
||||
return(p_adar->p_rx_buffer[2]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Block memory write to an ADAR device.
|
||||
*
|
||||
* @pre ADDR_ASCN bits in register zero must be set!
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
* @param mem_addr Memory address of the register you wish to read from.
|
||||
* @param p_data Pointer to block of data to transfer (must have two unused bytes preceding the data for instruction).
|
||||
* @param size Size of data in bytes, including the two additional leading bytes.
|
||||
*
|
||||
* @warning First two bytes of data will be corrupted if you do not provide two unused leading bytes!
|
||||
*/
|
||||
void Adar_ReadBlock(const AdarDevice * p_adar, uint16_t mem_addr, uint8_t * p_data, uint32_t size)
|
||||
{
|
||||
// Set SDO active
|
||||
Adar_Write(p_adar, REG_INTERFACE_CONFIG_A, INTERFACE_CONFIG_A_SDO_ACTIVE | INTERFACE_CONFIG_A_ADDR_ASCN, 0);
|
||||
|
||||
// Prepare command
|
||||
p_data[0] = 0x80 | ((p_adar->dev_addr & 0x03) << 5);
|
||||
p_data[0] |= ((mem_addr) >> 8) & 0x1F;
|
||||
p_data[1] = (0xFF & mem_addr);
|
||||
|
||||
// Start the transfer
|
||||
p_adar->Transfer(p_data, p_data, size);
|
||||
|
||||
Adar_Write(p_adar, REG_INTERFACE_CONFIG_A, 0, 0);
|
||||
// Return nothing since we assume this is non-blocking and won't wait around
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the Rx/Tx bias currents for the LNA, VM, and VGA to be in either
|
||||
* low power setting or nominal setting.
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
* @param p_bias[in] An AdarBiasCurrents struct filled with bias settings
|
||||
* as seen in the datasheet Table 6. SPI Settings for
|
||||
* Different Power Modules
|
||||
* @param broadcast Send the message as a broadcast to all ADARs in the SPI chain
|
||||
* if this set to BROADCAST_ON.
|
||||
*
|
||||
* @return Returns ADAR_ERR_NOERROR if the bias currents were set
|
||||
*/
|
||||
uint8_t Adar_SetBiasCurrents(const AdarDevice * p_adar, AdarBiasCurrents * p_bias, uint8_t broadcast)
|
||||
{
|
||||
uint8_t bias = 0;
|
||||
|
||||
// RX LNA/VGA/VM bias
|
||||
bias = (p_bias->rx_lna & 0x0f);
|
||||
Adar_Write(p_adar, REG_BIAS_CURRENT_RX_LNA, bias, broadcast); // RX LNA bias
|
||||
bias = (p_bias->rx_vga & 0x07 << 3) | (p_bias->rx_vm & 0x07);
|
||||
Adar_Write(p_adar, REG_BIAS_CURRENT_RX, bias, broadcast); // RX VM/VGA bias
|
||||
|
||||
// TX VGA/VM/DRV bias
|
||||
bias = (p_bias->tx_vga & 0x07 << 3) | (p_bias->tx_vm & 0x07);
|
||||
Adar_Write(p_adar, REG_BIAS_CURRENT_TX, bias, broadcast); // TX VM/VGA bias
|
||||
bias = (p_bias->tx_drv & 0x07);
|
||||
Adar_Write(p_adar, REG_BIAS_CURRENT_TX_DRV, bias, broadcast); // TX DRV bias
|
||||
|
||||
return(ADAR_ERROR_NOERROR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the bias ON and bias OFF voltages for the four PA's and one LNA.
|
||||
*
|
||||
* @pre This will set all 5 bias ON values and all 5 bias OFF values at once.
|
||||
* To enable these bias values, please see the data sheet and ensure that the BIAS_CTRL,
|
||||
* LNA_BIAS_OUT_EN, TR_SOURCE, TX_EN, RX_EN, TR (input to chip), and PA_ON (input to chip)
|
||||
* bits have all been properly set.
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
* @param bias_on_voltage Array that contains the bias ON voltages.
|
||||
* @param bias_off_voltage Array that contains the bias OFF voltages.
|
||||
*
|
||||
* @return Returns ADAR_ERR_NOERROR if the bias currents were set
|
||||
*/
|
||||
uint8_t Adar_SetBiasVoltages(const AdarDevice * p_adar, uint8_t bias_on_voltage[5], uint8_t bias_off_voltage[5])
|
||||
{
|
||||
Adar_SetBit(p_adar, 0x30, 6, BROADCAST_OFF);
|
||||
Adar_SetBit(p_adar, 0x31, 2, BROADCAST_OFF);
|
||||
Adar_SetBit(p_adar, 0x38, 5, BROADCAST_OFF);
|
||||
Adar_Write(p_adar, REG_PA_CH1_BIAS_ON,bias_on_voltage[0], BROADCAST_OFF);
|
||||
Adar_Write(p_adar, REG_PA_CH2_BIAS_ON,bias_on_voltage[1], BROADCAST_OFF);
|
||||
Adar_Write(p_adar, REG_PA_CH3_BIAS_ON,bias_on_voltage[2], BROADCAST_OFF);
|
||||
Adar_Write(p_adar, REG_PA_CH4_BIAS_ON,bias_on_voltage[3], BROADCAST_OFF);
|
||||
|
||||
Adar_Write(p_adar, REG_PA_CH1_BIAS_OFF,bias_off_voltage[0], BROADCAST_OFF);
|
||||
Adar_Write(p_adar, REG_PA_CH2_BIAS_OFF,bias_off_voltage[1], BROADCAST_OFF);
|
||||
Adar_Write(p_adar, REG_PA_CH3_BIAS_OFF,bias_off_voltage[2], BROADCAST_OFF);
|
||||
Adar_Write(p_adar, REG_PA_CH4_BIAS_OFF,bias_off_voltage[3], BROADCAST_OFF);
|
||||
|
||||
Adar_SetBit(p_adar, 0x30, 4, BROADCAST_OFF);
|
||||
Adar_SetBit(p_adar, 0x30, 6, BROADCAST_OFF);
|
||||
Adar_SetBit(p_adar, 0x31, 2, BROADCAST_OFF);
|
||||
Adar_SetBit(p_adar, 0x38, 5, BROADCAST_OFF);
|
||||
Adar_Write(p_adar, REG_LNA_BIAS_ON,bias_on_voltage[4], BROADCAST_OFF);
|
||||
Adar_Write(p_adar, REG_LNA_BIAS_OFF,bias_off_voltage[4], BROADCAST_OFF);
|
||||
|
||||
Adar_ResetBit(p_adar, 0x30, 7, BROADCAST_OFF);
|
||||
Adar_SetBit(p_adar, 0x31, 2, BROADCAST_OFF);
|
||||
Adar_SetBit(p_adar, 0x31, 4, BROADCAST_OFF);
|
||||
Adar_SetBit(p_adar, 0x31, 7, BROADCAST_OFF);
|
||||
|
||||
return(ADAR_ERROR_NOERROR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Setup the ADAR to use settings that are transferred over SPI.
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
* @param broadcast Send the message as a broadcast to all ADARs in the SPI chain
|
||||
* if this set to BROADCAST_ON.
|
||||
*
|
||||
* @return Returns ADAR_ERR_NOERROR if the bias currents were set
|
||||
*/
|
||||
uint8_t Adar_SetRamBypass(const AdarDevice * p_adar, uint8_t broadcast)
|
||||
{
|
||||
uint8_t data;
|
||||
|
||||
data = (MEM_CTRL_BIAS_RAM_BYPASS | MEM_CTRL_BEAM_RAM_BYPASS);
|
||||
|
||||
Adar_Write(p_adar, REG_MEM_CTL, data, broadcast);
|
||||
|
||||
return(ADAR_ERROR_NOERROR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the VGA gain value of a Receive channel in dB.
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
* @param channel Channel in which to set the gain (1-4).
|
||||
* @param vga_gain_db Gain to be applied to the channel, ranging from 0 - 30 dB.
|
||||
* (Intended operation >16 dB).
|
||||
* @param broadcast Send the message as a broadcast to all ADARs in the SPI chain
|
||||
* if this set to BROADCAST_ON.
|
||||
*
|
||||
* @return Returns ADAR_ERROR_NOERROR if the gain was successfully set.
|
||||
* ADAR_ERROR_FAILED if an invalid channel was selected.
|
||||
*
|
||||
* @warning 0 dB or 15 dB step attenuator may also be turned on, which is why intended operation is >16 dB.
|
||||
*/
|
||||
uint8_t Adar_SetRxVgaGain(const AdarDevice * p_adar, uint8_t channel, uint8_t vga_gain_db, uint8_t broadcast)
|
||||
{
|
||||
uint8_t vga_gain_bits = (uint8_t)(255*vga_gain_db/16);
|
||||
uint32_t mem_addr = 0;
|
||||
|
||||
if((channel == 0) || (channel > 4))
|
||||
{
|
||||
return(ADAR_ERROR_FAILED);
|
||||
}
|
||||
|
||||
mem_addr = REG_CH1_RX_GAIN + (channel & 0x03);
|
||||
|
||||
// Set gain
|
||||
Adar_Write(p_adar, mem_addr, vga_gain_bits, broadcast);
|
||||
|
||||
// Load the new setting
|
||||
Adar_Write(p_adar, REG_LOAD_WORKING, 0x1, broadcast);
|
||||
|
||||
return(ADAR_ERROR_NOERROR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the phase of a given receive channel using the I/Q vector modulator.
|
||||
*
|
||||
* @pre According to the given @param phase, this sets the polarity (bit 5) and gain (bits 4-0)
|
||||
* of the @param channel, and then loads them into the working register.
|
||||
* A vector modulator I/Q look-up table has been provided at the beginning of this library.
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
* @param channel Channel in which to set the gain (1-4).
|
||||
* @param phase Byte that is used to set the polarity (bit 5) and gain (bits 4-0).
|
||||
* @param broadcast Send the message as a broadcast to all ADARs in the SPI chain
|
||||
* if this set to BROADCAST_ON.
|
||||
*
|
||||
* @return Returns ADAR_ERROR_NOERROR if the phase was successfully set.
|
||||
* ADAR_ERROR_FAILED if an invalid channel was selected.
|
||||
*
|
||||
* @note To obtain your phase:
|
||||
* phase = degrees * 128;
|
||||
* phase /= 360;
|
||||
*/
|
||||
uint8_t Adar_SetRxPhase(const AdarDevice * p_adar, uint8_t channel, uint8_t phase, uint8_t broadcast)
|
||||
{
|
||||
uint8_t i_val = 0;
|
||||
uint8_t q_val = 0;
|
||||
uint32_t mem_addr_i, mem_addr_q;
|
||||
|
||||
if((channel == 0) || (channel > 4))
|
||||
{
|
||||
return(ADAR_ERROR_FAILED);
|
||||
}
|
||||
|
||||
//phase = phase % 128;
|
||||
i_val = VM_I[phase];
|
||||
q_val = VM_Q[phase];
|
||||
|
||||
mem_addr_i = REG_CH1_RX_PHS_I + (channel & 0x03) * 2;
|
||||
mem_addr_q = REG_CH1_RX_PHS_Q + (channel & 0x03) * 2;
|
||||
|
||||
Adar_Write(p_adar, mem_addr_i, i_val, broadcast);
|
||||
Adar_Write(p_adar, mem_addr_q, q_val, broadcast);
|
||||
Adar_Write(p_adar, REG_LOAD_WORKING, 0x1, broadcast);
|
||||
|
||||
return(ADAR_ERROR_NOERROR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the VGA gain value of a Tx channel in dB.
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
* @param broadcast Send the message as a broadcast to all ADARs in the SPI chain
|
||||
* if this set to BROADCAST_ON.
|
||||
*
|
||||
* @return Returns ADAR_ERROR_NOERROR if the bias was successfully set.
|
||||
* ADAR_ERROR_FAILED if an invalid channel was selected.
|
||||
*
|
||||
* @warning 0 dB or 15 dB step attenuator may also be turned on, which is why intended operation is >16 dB.
|
||||
*/
|
||||
uint8_t Adar_SetTxBias(const AdarDevice * p_adar, uint8_t broadcast)
|
||||
{
|
||||
uint8_t vga_bias_bits;
|
||||
uint8_t drv_bias_bits;
|
||||
uint32_t mem_vga_bias;
|
||||
uint32_t mem_drv_bias;
|
||||
|
||||
mem_vga_bias = REG_BIAS_CURRENT_TX;
|
||||
mem_drv_bias = REG_BIAS_CURRENT_TX_DRV;
|
||||
|
||||
// Set bias to nom
|
||||
vga_bias_bits = 0x2D;
|
||||
drv_bias_bits = 0x06;
|
||||
|
||||
// Set bias
|
||||
Adar_Write(p_adar, mem_vga_bias, vga_bias_bits, broadcast);
|
||||
// Set bias
|
||||
Adar_Write(p_adar, mem_drv_bias, drv_bias_bits, broadcast);
|
||||
|
||||
// Load the new setting
|
||||
Adar_Write(p_adar, REG_LOAD_WORKING, 0x2, broadcast);
|
||||
|
||||
return(ADAR_ERROR_NOERROR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the VGA gain value of a Tx channel.
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
* @param channel Tx channel in which to set the gain, ranging from 1 - 4.
|
||||
* @param gain Gain to be applied to the channel, ranging from 0 - 127,
|
||||
* plus the MSb 15dB attenuator (Intended operation >16 dB).
|
||||
* @param broadcast Send the message as a broadcast to all ADARs in the SPI chain
|
||||
* if this set to BROADCAST_ON.
|
||||
*
|
||||
* @return Returns ADAR_ERROR_NOERROR if the gain was successfully set.
|
||||
* ADAR_ERROR_FAILED if an invalid channel was selected.
|
||||
*
|
||||
* @warning 0 dB or 15 dB step attenuator may also be turned on, which is why intended operation is >16 dB.
|
||||
*/
|
||||
uint8_t Adar_SetTxVgaGain(const AdarDevice * p_adar, uint8_t channel, uint8_t gain, uint8_t broadcast)
|
||||
{
|
||||
uint32_t mem_addr;
|
||||
|
||||
if((channel == 0) || (channel > 4))
|
||||
{
|
||||
return(ADAR_ERROR_FAILED);
|
||||
}
|
||||
|
||||
mem_addr = REG_CH1_TX_GAIN + (channel & 0x03);
|
||||
|
||||
// Set gain
|
||||
Adar_Write(p_adar, mem_addr, gain, broadcast);
|
||||
|
||||
// Load the new setting
|
||||
Adar_Write(p_adar, REG_LOAD_WORKING, LD_WRK_REGS_LDTX_OVERRIDE, broadcast);
|
||||
|
||||
return(ADAR_ERROR_NOERROR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the phase of a given transmit channel using the I/Q vector modulator.
|
||||
*
|
||||
* @pre According to the given @param phase, this sets the polarity (bit 5) and gain (bits 4-0)
|
||||
* of the @param channel, and then loads them into the working register.
|
||||
* A vector modulator I/Q look-up table has been provided at the beginning of this library.
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
* @param channel Channel in which to set the gain (1-4).
|
||||
* @param phase Byte that is used to set the polarity (bit 5) and gain (bits 4-0).
|
||||
* @param broadcast Send the message as a broadcast to all ADARs in the SPI chain
|
||||
* if this set to BROADCAST_ON.
|
||||
*
|
||||
* @return Returns ADAR_ERROR_NOERROR if the phase was successfully set.
|
||||
* ADAR_ERROR_FAILED if an invalid channel was selected.
|
||||
*
|
||||
* @note To obtain your phase:
|
||||
* phase = degrees * 128;
|
||||
* phase /= 360;
|
||||
*/
|
||||
uint8_t Adar_SetTxPhase(const AdarDevice * p_adar, uint8_t channel, uint8_t phase, uint8_t broadcast)
|
||||
{
|
||||
uint8_t i_val = 0;
|
||||
uint8_t q_val = 0;
|
||||
uint32_t mem_addr_i, mem_addr_q;
|
||||
|
||||
if((channel == 0) || (channel > 4))
|
||||
{
|
||||
return(ADAR_ERROR_FAILED);
|
||||
}
|
||||
|
||||
//phase = phase % 128;
|
||||
i_val = VM_I[phase];
|
||||
q_val = VM_Q[phase];
|
||||
|
||||
mem_addr_i = REG_CH1_TX_PHS_I + (channel & 0x03) * 2;
|
||||
mem_addr_q = REG_CH1_TX_PHS_Q + (channel & 0x03) * 2;
|
||||
|
||||
Adar_Write(p_adar, mem_addr_i, i_val, broadcast);
|
||||
Adar_Write(p_adar, mem_addr_q, q_val, broadcast);
|
||||
Adar_Write(p_adar, REG_LOAD_WORKING, 0x1, broadcast);
|
||||
|
||||
return(ADAR_ERROR_NOERROR);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Reset the whole ADAR device.
|
||||
*
|
||||
* @param p_adar[in] ADAR pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
*/
|
||||
void Adar_SoftReset(const AdarDevice * p_adar)
|
||||
{
|
||||
uint8_t instruction[3];
|
||||
|
||||
instruction[0] = ((p_adar->dev_addr & 0x03) << 5);
|
||||
instruction[1] = 0x00;
|
||||
instruction[2] = 0x81;
|
||||
|
||||
p_adar->Transfer(instruction, NULL, sizeof(instruction));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Reset ALL ADAR devices in the SPI chain.
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
*/
|
||||
void Adar_SoftResetAll(const AdarDevice * p_adar)
|
||||
{
|
||||
uint8_t instruction[3];
|
||||
|
||||
instruction[0] = 0x08;
|
||||
instruction[1] = 0x00;
|
||||
instruction[2] = 0x81;
|
||||
|
||||
p_adar->Transfer(instruction, NULL, sizeof(instruction));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write a byte of @param data to the register located at @param mem_addr.
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
* @param mem_addr Memory address of the register you wish to read from.
|
||||
* @param data Byte of data to be stored in the register.
|
||||
* @param broadcast Send the message as a broadcast to all ADARs in the SPI chain
|
||||
if this set to BROADCAST_ON.
|
||||
*
|
||||
* @warning If writing the same data to multiple registers, use ADAR_WriteBlock.
|
||||
*/
|
||||
void Adar_Write(const AdarDevice * p_adar, uint32_t mem_addr, uint8_t data, uint8_t broadcast)
|
||||
{
|
||||
uint8_t instruction[3];
|
||||
|
||||
if (broadcast)
|
||||
{
|
||||
instruction[0] = 0x08;
|
||||
}
|
||||
else
|
||||
{
|
||||
instruction[0] = ((p_adar->dev_addr & 0x03) << 5);
|
||||
}
|
||||
|
||||
instruction[0] |= (0x1F00 & mem_addr) >> 8;
|
||||
instruction[1] = (0xFF & mem_addr);
|
||||
instruction[2] = data;
|
||||
|
||||
p_adar->Transfer(instruction, NULL, sizeof(instruction));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Block memory write to an ADAR device.
|
||||
*
|
||||
* @pre ADDR_ASCN BITS IN REGISTER ZERO MUST BE SET!
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
* @param mem_addr Memory address of the register you wish to read from.
|
||||
* @param p_data[in] Pointer to block of data to transfer (must have two unused bytes
|
||||
preceding the data for instruction).
|
||||
* @param size Size of data in bytes, including the two additional leading bytes.
|
||||
*
|
||||
* @warning First two bytes of data will be corrupted if you do not provide two unused leading bytes!
|
||||
*/
|
||||
void Adar_WriteBlock(const AdarDevice * p_adar, uint16_t mem_addr, uint8_t * p_data, uint32_t size)
|
||||
{
|
||||
// Prepare command
|
||||
p_data[0] = ((p_adar->dev_addr & 0x03) << 5);
|
||||
p_data[0] |= ((mem_addr) >> 8) & 0x1F;
|
||||
p_data[1] = (0xFF & mem_addr);
|
||||
|
||||
// Start the transfer
|
||||
p_adar->Transfer(p_data, NULL, size);
|
||||
|
||||
// Return nothing since we assume this is non-blocking and won't wait around
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set contents of the INTERFACE_CONFIG_A register.
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
* @param flags #INTERFACE_CONFIG_A_SOFTRESET, #INTERFACE_CONFIG_A_LSB_FIRST,
|
||||
* #INTERFACE_CONFIG_A_ADDR_ASCN, #INTERFACE_CONFIG_A_SDO_ACTIVE
|
||||
* @param broadcast Send the message as a broadcast to all ADARs in the SPI chain
|
||||
* if this set to BROADCAST_ON.
|
||||
*/
|
||||
void Adar_WriteConfigA(const AdarDevice * p_adar, uint8_t flags, uint8_t broadcast)
|
||||
{
|
||||
Adar_Write(p_adar, 0x00, flags, broadcast);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write a byte of @param data to the register located at @param mem_addr and
|
||||
* then read from the device and verify that the register was correctly set.
|
||||
*
|
||||
* @param p_adar[in] Adar pointer Which specifies the device and what function
|
||||
* to use for SPI transfer.
|
||||
* @param mem_addr Memory address of the register you wish to read from.
|
||||
* @param data Byte of data to be stored in the register.
|
||||
*
|
||||
* @return Returns the number of attempts that it took to successfully write to a register,
|
||||
* starting from zero.
|
||||
* @warning This function currently only supports writes to a single regiter in a single ADAR.
|
||||
*/
|
||||
uint8_t Adar_WriteVerify(const AdarDevice * p_adar, uint32_t mem_addr, uint8_t data)
|
||||
{
|
||||
uint8_t rx_data;
|
||||
|
||||
for (uint8_t ii = 0; ii < 3; ii++)
|
||||
{
|
||||
Adar_Write(p_adar, mem_addr, data, 0);
|
||||
|
||||
// Can't read back from an ADAR with HW address 0
|
||||
if (!((p_adar->dev_addr) % 4))
|
||||
{
|
||||
return(ADAR_ERROR_INVALIDADDR);
|
||||
}
|
||||
rx_data = Adar_Read(p_adar, mem_addr);
|
||||
if (rx_data == data)
|
||||
{
|
||||
return(ii);
|
||||
}
|
||||
}
|
||||
|
||||
return(ADAR_ERROR_FAILED);
|
||||
}
|
||||
|
||||
void Adar_SetBit(const AdarDevice * p_adar, uint32_t mem_addr, uint8_t bit, uint8_t broadcast)
|
||||
{
|
||||
uint8_t temp = Adar_Read(p_adar, mem_addr);
|
||||
uint8_t data = temp|(1<<bit);
|
||||
Adar_Write(p_adar,mem_addr, data,broadcast);
|
||||
}
|
||||
|
||||
void Adar_ResetBit(const AdarDevice * p_adar, uint32_t mem_addr, uint8_t bit, uint8_t broadcast)
|
||||
{
|
||||
uint8_t temp = Adar_Read(p_adar, mem_addr);
|
||||
uint8_t data = temp&~(1<<bit);
|
||||
Adar_Write(p_adar,mem_addr, data,broadcast);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 Jimmy Pentz
|
||||
*
|
||||
* Reach me at: github.com/jgpentz, jpentz1( at )gmail.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sells
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
/* ADAR1000 4-Channel, X Band and Ku Band Beamformer */
|
||||
#ifndef LIB_ADAR1000_H_
|
||||
#define LIB_ADAR1000_H_
|
||||
|
||||
extern SPI_HandleTypeDef hspi1;
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL (0)
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Includes
|
||||
// ----------------------------------------------------------------------------
|
||||
#include "main.h"
|
||||
#include "hardware_config.h"
|
||||
#include "stm32f7xx_hal.h"
|
||||
#include "stm32f7xx_hal_spi.h"
|
||||
#include "stm32f7xx_hal_gpio.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" { // Prevent C++ name mangling
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Datatypes
|
||||
// ----------------------------------------------------------------------------
|
||||
extern const uint8_t VM_GAIN[128];
|
||||
extern const uint8_t VM_I[128];
|
||||
extern const uint8_t VM_Q[128];
|
||||
|
||||
/// A function pointer prototype for a SPI transfer, the 3 parameters would be
|
||||
/// p_txData, p_rxData, and size (number of bytes to transfer), respectively.
|
||||
typedef uint32_t (*Adar_SpiTransfer)( uint8_t *, uint8_t *, uint32_t);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t dev_addr; ///< 2-bit device hardware address, 0x00, 0x01, 0x10, 0x11
|
||||
Adar_SpiTransfer Transfer; ///< Function pointer to the function used for SPI transfers
|
||||
uint8_t * p_rx_buffer; ///< Data buffer to store received bytes into
|
||||
}const AdarDevice;
|
||||
|
||||
|
||||
/// Use this to store bias current values into, as seen in the datasheet
|
||||
/// Table 6. SPI Settings for Different Power Modules
|
||||
typedef struct
|
||||
{
|
||||
uint8_t rx_lna; ///< nominal: 8, low power: 5
|
||||
uint8_t rx_vm; ///< nominal: 5, low power: 2
|
||||
uint8_t rx_vga; ///< nominal: 10, low power: 3
|
||||
uint8_t tx_vm; ///< nominal: 5, low power: 2
|
||||
uint8_t tx_vga; ///< nominal: 5, low power: 5
|
||||
uint8_t tx_drv; ///< nominal: 6, low power: 3
|
||||
} AdarBiasCurrents;
|
||||
|
||||
/// Useful for queries regarding the device info
|
||||
typedef struct
|
||||
{
|
||||
uint8_t norm_operating_mode : 2;
|
||||
uint8_t cust_operating_mode : 2;
|
||||
uint8_t dev_status : 4;
|
||||
uint8_t chip_type;
|
||||
uint16_t product_id;
|
||||
uint8_t scratchpad;
|
||||
uint8_t spi_rev;
|
||||
uint16_t vendor_id;
|
||||
uint8_t rev_id;
|
||||
} AdarDeviceInfo;
|
||||
|
||||
/// Return types for functions in this library
|
||||
typedef enum {
|
||||
ADAR_ERROR_NOERROR = 0,
|
||||
ADAR_ERROR_FAILED = 1,
|
||||
ADAR_ERROR_INVALIDADDR = 2,
|
||||
} AdarErrorCodes;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Function Prototypes
|
||||
// ----------------------------------------------------------------------------
|
||||
void Adar_AdcInit(const AdarDevice * p_adar, uint8_t broadcast_bit);
|
||||
|
||||
uint8_t Adar_AdcRead(const AdarDevice * p_adar, uint8_t broadcast_bit);
|
||||
|
||||
uint8_t Adar_GetDeviceInfo(const AdarDevice * p_adar, AdarDeviceInfo * info);
|
||||
|
||||
uint8_t Adar_Read(const AdarDevice * p_adar, uint32_t mem_addr);
|
||||
|
||||
void Adar_ReadBlock(const AdarDevice * p_adar, uint16_t mem_addr, uint8_t * p_data, uint32_t size);
|
||||
|
||||
uint8_t Adar_SetBiasCurrents(const AdarDevice * p_adar, AdarBiasCurrents * p_bias, uint8_t broadcast_bit);
|
||||
|
||||
uint8_t Adar_SetBiasVoltages(const AdarDevice * p_adar, uint8_t bias_on_voltage[5], uint8_t bias_off_voltage[5]);
|
||||
|
||||
uint8_t Adar_SetRamBypass(const AdarDevice * p_adar, uint8_t broadcast_bit);
|
||||
|
||||
uint8_t Adar_SetRxVgaGain(const AdarDevice * p_adar, uint8_t channel, uint8_t vga_gain_db, uint8_t broadcast_bit);
|
||||
|
||||
uint8_t Adar_SetRxPhase(const AdarDevice * p_adar, uint8_t channel, uint8_t phase, uint8_t broadcast_bit);
|
||||
|
||||
uint8_t Adar_SetTxBias(const AdarDevice * p_adar, uint8_t broadcast_bit);
|
||||
|
||||
uint8_t Adar_SetTxVgaGain(const AdarDevice * p_adar, uint8_t channel, uint8_t vga_gain_db, uint8_t broadcast_bit);
|
||||
|
||||
uint8_t Adar_SetTxPhase(const AdarDevice * p_adar, uint8_t channel, uint8_t phase, uint8_t broadcast_bit);
|
||||
|
||||
void Adar_SoftReset(const AdarDevice * p_adar);
|
||||
|
||||
void Adar_SoftResetAll(const AdarDevice * p_adar);
|
||||
|
||||
void Adar_Write(const AdarDevice * p_adar, uint32_t mem_addr, uint8_t data, uint8_t broadcast_bit);
|
||||
|
||||
void Adar_WriteBlock(const AdarDevice * p_adar, uint16_t mem_addr, uint8_t * p_data, uint32_t size);
|
||||
|
||||
void Adar_WriteConfigA(const AdarDevice * p_adar, uint8_t flags, uint8_t broadcast);
|
||||
|
||||
uint8_t Adar_WriteVerify(const AdarDevice * p_adar, uint32_t mem_addr, uint8_t data);
|
||||
|
||||
void Adar_SetBit(const AdarDevice * p_adar, uint32_t mem_addr, uint8_t bit, uint8_t broadcast);
|
||||
|
||||
void Adar_ResetBit(const AdarDevice * p_adar, uint32_t mem_addr, uint8_t bit, uint8_t broadcast);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Preprocessor Definitions and Constants
|
||||
// ----------------------------------------------------------------------------
|
||||
// Using BROADCAST_ON will send a command to all ADARs that share a bus
|
||||
#define BROADCAST_OFF 0
|
||||
#define BROADCAST_ON 1
|
||||
|
||||
// The minimum size of a read from the ADARs consists of 3 bytes
|
||||
#define ADAR1000_RD_SIZE 3
|
||||
|
||||
// Address at which the TX RAM starts
|
||||
#define ADAR_TX_RAM_START_ADDR 0x1800
|
||||
|
||||
// ADC Defines
|
||||
#define ADAR1000_ADC_2MHZ_CLK 0x00
|
||||
#define ADAR1000_ADC_EN 0x60
|
||||
#define ADAR1000_ADC_ST_CONV 0x70
|
||||
|
||||
/* REGISTER DEFINITIONS */
|
||||
#define REG_INTERFACE_CONFIG_A 0x000
|
||||
#define REG_INTERFACE_CONFIG_B 0x001
|
||||
#define REG_DEV_CONFIG 0x002
|
||||
#define REG_SCRATCHPAD 0x00A
|
||||
#define REG_TRANSFER 0x00F
|
||||
#define REG_CH1_RX_GAIN 0x010
|
||||
#define REG_CH2_RX_GAIN 0x011
|
||||
#define REG_CH3_RX_GAIN 0x012
|
||||
#define REG_CH4_RX_GAIN 0x013
|
||||
#define REG_CH1_RX_PHS_I 0x014
|
||||
#define REG_CH1_RX_PHS_Q 0x015
|
||||
#define REG_CH2_RX_PHS_I 0x016
|
||||
#define REG_CH2_RX_PHS_Q 0x017
|
||||
#define REG_CH3_RX_PHS_I 0x018
|
||||
#define REG_CH3_RX_PHS_Q 0x019
|
||||
#define REG_CH4_RX_PHS_I 0x01A
|
||||
#define REG_CH4_RX_PHS_Q 0x01B
|
||||
#define REG_CH1_TX_GAIN 0x01C
|
||||
#define REG_CH2_TX_GAIN 0x01D
|
||||
#define REG_CH3_TX_GAIN 0x01E
|
||||
#define REG_CH4_TX_GAIN 0x01F
|
||||
#define REG_CH1_TX_PHS_I 0x020
|
||||
#define REG_CH1_TX_PHS_Q 0x021
|
||||
#define REG_CH2_TX_PHS_I 0x022
|
||||
#define REG_CH2_TX_PHS_Q 0x023
|
||||
#define REG_CH3_TX_PHS_I 0x024
|
||||
#define REG_CH3_TX_PHS_Q 0x025
|
||||
#define REG_CH4_TX_PHS_I 0x026
|
||||
#define REG_CH4_TX_PHS_Q 0x027
|
||||
#define REG_LOAD_WORKING 0x028
|
||||
#define REG_PA_CH1_BIAS_ON 0x029
|
||||
#define REG_PA_CH2_BIAS_ON 0x02A
|
||||
#define REG_PA_CH3_BIAS_ON 0x02B
|
||||
#define REG_PA_CH4_BIAS_ON 0x02C
|
||||
#define REG_LNA_BIAS_ON 0x02D
|
||||
#define REG_RX_ENABLES 0x02E
|
||||
#define REG_TX_ENABLES 0x02F
|
||||
#define REG_MISC_ENABLES 0x030
|
||||
#define REG_SW_CONTROL 0x031
|
||||
#define REG_ADC_CONTROL 0x032
|
||||
#define REG_ADC_CONTROL_TEMP_EN 0xf0
|
||||
#define REG_ADC_OUT 0x033
|
||||
#define REG_BIAS_CURRENT_RX_LNA 0x034
|
||||
#define REG_BIAS_CURRENT_RX 0x035
|
||||
#define REG_BIAS_CURRENT_TX 0x036
|
||||
#define REG_BIAS_CURRENT_TX_DRV 0x037
|
||||
#define REG_MEM_CTL 0x038
|
||||
#define REG_RX_CHX_MEM 0x039
|
||||
#define REG_TX_CHX_MEM 0x03A
|
||||
#define REG_RX_CH1_MEM 0x03D
|
||||
#define REG_RX_CH2_MEM 0x03E
|
||||
#define REG_RX_CH3_MEM 0x03F
|
||||
#define REG_RX_CH4_MEM 0x040
|
||||
#define REG_TX_CH1_MEM 0x041
|
||||
#define REG_TX_CH2_MEM 0x042
|
||||
#define REG_TX_CH3_MEM 0x043
|
||||
#define REG_TX_CH4_MEM 0x044
|
||||
#define REG_PA_CH1_BIAS_OFF 0x046
|
||||
#define REG_PA_CH2_BIAS_OFF 0x047
|
||||
#define REG_PA_CH3_BIAS_OFF 0x048
|
||||
#define REG_PA_CH4_BIAS_OFF 0x049
|
||||
#define REG_LNA_BIAS_OFF 0x04A
|
||||
#define REG_TX_BEAM_STEP_START 0x04D
|
||||
#define REG_TX_BEAM_STEP_STOP 0x04E
|
||||
#define REG_RX_BEAM_STEP_START 0x04F
|
||||
#define REG_RX_BEAM_STEP_STOP 0x050
|
||||
|
||||
// REGISTER CONSTANTS
|
||||
#define INTERFACE_CONFIG_A_SOFTRESET ((1 << 7) | (1 << 0))
|
||||
#define INTERFACE_CONFIG_A_LSB_FIRST ((1 << 6) | (1 << 1))
|
||||
#define INTERFACE_CONFIG_A_ADDR_ASCN ((1 << 5) | (1 << 2))
|
||||
#define INTERFACE_CONFIG_A_SDO_ACTIVE ((1 << 4) | (1 << 3))
|
||||
|
||||
#define LD_WRK_REGS_LDRX_OVERRIDE (1 << 0)
|
||||
#define LD_WRK_REGS_LDTX_OVERRIDE (1 << 1)
|
||||
|
||||
#define RX_ENABLES_TX_VGA_EN (1 << 0)
|
||||
#define RX_ENABLES_TX_VM_EN (1 << 1)
|
||||
#define RX_ENABLES_TX_DRV_EN (1 << 2)
|
||||
#define RX_ENABLES_CH3_TX_EN (1 << 3)
|
||||
#define RX_ENABLES_CH2_TX_EN (1 << 4)
|
||||
#define RX_ENABLES_CH1_TX_EN (1 << 5)
|
||||
#define RX_ENABLES_CH0_TX_EN (1 << 6)
|
||||
|
||||
#define TX_ENABLES_TX_VGA_EN (1 << 0)
|
||||
#define TX_ENABLES_TX_VM_EN (1 << 1)
|
||||
#define TX_ENABLES_TX_DRV_EN (1 << 2)
|
||||
#define TX_ENABLES_CH3_TX_EN (1 << 3)
|
||||
#define TX_ENABLES_CH2_TX_EN (1 << 4)
|
||||
#define TX_ENABLES_CH1_TX_EN (1 << 5)
|
||||
#define TX_ENABLES_CH0_TX_EN (1 << 6)
|
||||
|
||||
#define MISC_ENABLES_CH4_DET_EN (1 << 0)
|
||||
#define MISC_ENABLES_CH3_DET_EN (1 << 1)
|
||||
#define MISC_ENABLES_CH2_DET_EN (1 << 2)
|
||||
#define MISC_ENABLES_CH1_DET_EN (1 << 3)
|
||||
#define MISC_ENABLES_LNA_BIAS_OUT_EN (1 << 4)
|
||||
#define MISC_ENABLES_BIAS_EN (1 << 5)
|
||||
#define MISC_ENABLES_BIAS_CTRL (1 << 6)
|
||||
#define MISC_ENABLES_SW_DRV_TR_MODE_SEL (1 << 7)
|
||||
|
||||
#define SW_CTRL_POL (1 << 0)
|
||||
#define SW_CTRL_TR_SPI (1 << 1)
|
||||
#define SW_CTRL_TR_SOURCE (1 << 2)
|
||||
#define SW_CTRL_SW_DRV_EN_POL (1 << 3)
|
||||
#define SW_CTRL_SW_DRV_EN_TR (1 << 4)
|
||||
#define SW_CTRL_RX_EN (1 << 5)
|
||||
#define SW_CTRL_TX_EN (1 << 6)
|
||||
#define SW_CTRL_SW_DRV_TR_STATE (1 << 7)
|
||||
|
||||
#define MEM_CTRL_RX_CHX_RAM_BYPASS (1 << 0)
|
||||
#define MEM_CTRL_TX_CHX_RAM_BYPASS (1 << 1)
|
||||
#define MEM_CTRL_RX_BEAM_STEP_EN (1 << 2)
|
||||
#define MEM_CTRL_TX_BEAM_STEP_EN (1 << 3)
|
||||
#define MEM_CTRL_BIAS_RAM_BYPASS (1 << 5)
|
||||
#define MEM_CTRL_BEAM_RAM_BYPASS (1 << 6)
|
||||
#define MEM_CTRL_SCAN_MODE_EN (1 << 7)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // End extern "C"
|
||||
#endif
|
||||
|
||||
#endif /* LIB_ADAR1000_H_ */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,803 @@
|
||||
/***************************************************************************//**
|
||||
* @file adf4382.h
|
||||
* @brief Implementation of adf4382 Driver.
|
||||
* @authors Ciprian Hegbeli (ciprian.hegbeli@analog.com)
|
||||
* Jude Osemene (jude.osemene@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2024(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "no_os_units.h"
|
||||
#include "no_os_util.h"
|
||||
#include "no_os_spi.h"
|
||||
|
||||
/* ADF4382 REG0000 Map */
|
||||
#define ADF4382_SOFT_RESET_R_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_LSB_FIRST_R_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_ADDRESS_ASC_R_MSK NO_OS_BIT(5)
|
||||
#define ADF4382_SDO_ACTIVE_R_MSK NO_OS_BIT(4)
|
||||
#define ADF4382_SDO_ACTIVE_MSK NO_OS_BIT(3)
|
||||
#define ADF4382_ADDRESS_ASC_MSK NO_OS_BIT(2)
|
||||
#define ADF4382_LSB_FIRST_MSK NO_OS_BIT(1)
|
||||
#define ADF4382_SOFT_RESET_MSK NO_OS_BIT(0)
|
||||
#define ADF4382_RESET_CMD 0x81
|
||||
|
||||
/* ADF4382 REG0000 NO_OS_BIT Definition */
|
||||
#define ADF4382_SDO_ACTIVE_SPI_3W 0x0
|
||||
#define ADF4382_SDO_ACTIVE_SPI_4W 0x1
|
||||
|
||||
#define ADF4382_ADDR_ASC_AUTO_DECR 0x0
|
||||
#define ADF4382_ADDR_ASC_AUTO_INCR 0x1
|
||||
|
||||
#define ADF4382_LSB_FIRST_MSB 0x0
|
||||
#define ADF4382_LSB_FIRST_LSB 0x1
|
||||
|
||||
#define ADF4382_SOFT_RESET_N_OP 0x0
|
||||
#define ADF4382_SOFT_RESET_EN 0x1
|
||||
|
||||
/* ADF4382 REG0001 Map */
|
||||
#define ADF4382_SINGLE_INSTR_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_MASTER_RB_CTRL_MSK NO_OS_BIT(5)
|
||||
|
||||
/* ADF4382 REG0001 NO_OS_BIT Definition */
|
||||
#define ADF4382_SPI_STREAM_EN 0x0
|
||||
#define ADF4382_SPI_STREAM_DIS 0x1
|
||||
|
||||
#define ADF4382_RB_SLAVE_REG 0x0
|
||||
#define ADF4382_RB_MASTER_REG 0x1
|
||||
|
||||
/* ADF4382 REG0003 NO_OS_BIT Definition */
|
||||
#define ADF4382_CHIP_TYPE 0x06
|
||||
|
||||
/* ADF4382 REG0004 NO_OS_BIT Definition */
|
||||
#define ADF4382_PRODUCT_ID_LSB 0x0005
|
||||
|
||||
/* ADF4382 REG0005 NO_OS_BIT Definition */
|
||||
#define ADF4382_PRODUCT_ID_MSB 0x0005
|
||||
|
||||
/* ADF4382 REG000A Map */
|
||||
#define ADF4382_SCRATCHPAD_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG000C NO_OS_BIT Definition */
|
||||
#define ADF4382_VENDOR_ID_LSB 0x56
|
||||
|
||||
/* ADF4382 REG000D NO_OS_BIT Definition */
|
||||
#define ADF4382_VENDOR_ID_MSB 0x04
|
||||
|
||||
/* ADF4382 REG000F NO_OS_BIT Definition */
|
||||
#define ADF4382_M_S_TRANSF_NO_OS_BIT_MSK NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG0010 Map*/
|
||||
#define ADF4382_N_INT_LSB_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0011 Map*/
|
||||
#define ADF4382_CLKOUT_DIV_MSK NO_OS_GENMASK(7, 5)
|
||||
#define ADF4382_INV_CLK_OUT_MSK NO_OS_BIT(4)
|
||||
#define ADF4382_N_INT_MSB_MSK NO_OS_GENMASK(3, 0)
|
||||
|
||||
/* ADF4382 REG0012 Map */
|
||||
#define ADF4382_FRAC1WORD_LSB_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0013 Map */
|
||||
#define ADF4382_FRAC1WORD_MID_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0014 Map */
|
||||
#define ADF4382_FRAC1WORD_MSB_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0015 Map */
|
||||
#define ADF4382_M_VCO_BAND_LSB_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_M_VCO_CORE_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_BIAS_DEC_MODE_MSK NO_OS_GENMASK(5, 3)
|
||||
#define ADF4382_INT_MODE_MSK NO_OS_BIT(2)
|
||||
#define ADF4382_PFD_POL_MSK NO_OS_BIT(1)
|
||||
#define ADF4382_FRAC1WORD_MSB NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG0016 Map */
|
||||
#define ADF4382_M_VCO_BAND_MSB_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0017 Map */
|
||||
#define ADF4382_FRAC2WORD_LSB_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0018 Map */
|
||||
#define ADF4382_FRAC2WORD_MID_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0019 Map */
|
||||
#define ADF4382_FRAC2WORD_MSB_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG001A Map */
|
||||
#define ADF4382_MOD2WORD_LSB_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG001B Map */
|
||||
#define ADF4382_MOD2WORD_MID_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG001C Map */
|
||||
#define ADF4382_MOD2WORD_MSB_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG001D Map */
|
||||
#define ADF4382_FINE_BLEED_LSB_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG001E Map */
|
||||
#define ADF4382_EN_PHASE_RESYNC_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_EN_REF_RST_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_TIMED_SYNC_MSK NO_OS_BIT(5)
|
||||
#define ADF4382_COARSE_BLEED_MSK NO_OS_GENMASK(4, 1)
|
||||
#define ADF4382_FINE_BLEED_MSB_MSK NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG001F Map */
|
||||
#define ADF4382_SW_SYNC_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_SPARE_1F_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_BLEED_POL_MSK NO_OS_BIT(5)
|
||||
#define ADF4382_EN_BLEED_MSK NO_OS_BIT(4)
|
||||
#define ADF4382_CP_I_MSK NO_OS_GENMASK(3, 0)
|
||||
|
||||
/* ADF4382 REG0020 Map */
|
||||
#define ADF4382_EN_AUTOCAL_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_EN_RDBLR_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_R_DIV_MSK NO_OS_GENMASK(5, 0)
|
||||
|
||||
/* ADF4382 REG0021 Map */
|
||||
#define ADF4382_PHASE_WORD_LSB_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0022 Map */
|
||||
#define ADF4382_PHASE_WORD_MID_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0023 Map */
|
||||
#define ADF4382_PHASE_WORD_MSB_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0024 Map */
|
||||
#define ADF4382_SPARE_24_MSK NO_OS_GENMASK(7, 5)
|
||||
#define ADF4382_DCLK_DIV_SEL_MSK NO_OS_BIT(4)
|
||||
#define ADF4382_DNCLK_DIV1_MSK NO_OS_GENMASK(3, 2)
|
||||
#define ADF4382_DCLK_DIV1_MSK NO_OS_GENMASK(1, 0)
|
||||
|
||||
/* ADF4382 REG0025 Map */
|
||||
#define ADF4382_RESYNC_WAIT_LSB_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0026 Map */
|
||||
#define ADF4382_RESYNC_WAIT_MSB_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0027 Map */
|
||||
#define ADF4382_CAL_BLEED_FINE_MIN_MSK NO_OS_GENMASK(7, 4)
|
||||
#define ADF4382_BLEED_ADJ_SCALE_MSK NO_OS_GENMASK(3, 0)
|
||||
|
||||
/* ADF4382 REG0028 Map */
|
||||
#define ADF4382_PH_RESYNC_RB_SEL_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_LSB_P1_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_VAR_MOD_EN_MSK NO_OS_BIT(5)
|
||||
#define ADF4382_DITHER1_SCALE_MSK NO_OS_GENMASK(4, 2)
|
||||
#define ADF4382_EN_DITHER2_MSK NO_OS_BIT(1)
|
||||
#define ADF4382_EN_DITHER1_MSK NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG0029 Map */
|
||||
#define ADF4382_CLK2_OPWR_MSK NO_OS_GENMASK(7, 4)
|
||||
#define ADF4382_CLK1_OPWR_MSK NO_OS_GENMASK(3, 0)
|
||||
|
||||
/* ADF4382 REG002A Map */
|
||||
#define ADF4382_FN_DBL_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_PD_NDIV_TL_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_CLKOUT_BST_MSK NO_OS_BIT(5)
|
||||
#define ADF4382_PD_SYNC_MSK NO_OS_BIT(4)
|
||||
#define ADF4382_PD_CLK_MSK NO_OS_BIT(3)
|
||||
#define ADF4382_PD_RDET_MSK NO_OS_BIT(2)
|
||||
#define ADF4382_PD_ADC_MSK NO_OS_BIT(1)
|
||||
#define ADF4382_PD_CALGEN_MSK NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG002B Map */
|
||||
#define ADF4382_PD_ALL_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_PD_RDIV_TL_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_PD_NDIV_MSK NO_OS_BIT(5)
|
||||
#define ADF4382_PD_VCO_MSK NO_OS_BIT(4)
|
||||
#define ADF4382_PD_LD_MSK NO_OS_BIT(3)
|
||||
#define ADF4382_PD_PFDCP_MSK NO_OS_BIT(2)
|
||||
#define ADF4382_PD_CLKOUT1_MSK NO_OS_BIT(1)
|
||||
#define ADF4382_PD_CLKOUT2_MSK NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG002C Map */
|
||||
#define ADF4382_LDWIN_PW_MSK NO_OS_GENMASK(7, 5)
|
||||
#define ADF4382_LD_COUNT_OPWR_MSK NO_OS_GENMASK(4, 0)
|
||||
|
||||
/* ADF4382 REG002D Map */
|
||||
#define ADF4382_EN_DNCLK_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_EN_DRCLK_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_EN_LOL_MSK NO_OS_BIT(5)
|
||||
#define ADF4382_EN_LDWIN_MSK NO_OS_BIT(4)
|
||||
#define ADF4382_PDET_POL_MSK NO_OS_BIT(3)
|
||||
#define ADF4382_RST_LD_MSK NO_OS_BIT(2)
|
||||
#define ADF4382_LD_O_CTRL_MSK NO_OS_GENMASK(1, 0)
|
||||
|
||||
/* ADF4382 REG002E Map */
|
||||
#define ADF4382_MUXOUT_MSK NO_OS_GENMASK(7, 4)
|
||||
#define ADF4382_ABPW_WD_MSK NO_OS_BIT(3)
|
||||
#define ADF4382_EN_CPTEST_MSK NO_OS_BIT(2)
|
||||
#define ADF4382_CP_DOWN_MSK NO_OS_BIT(1)
|
||||
#define ADF4382_CP_UP_MSK NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG002F Map*/
|
||||
#define ADF4382_BST_REF_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_FILT_REF_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_RDBLR_DC_MSK NO_OS_GENMASK(5, 0)
|
||||
|
||||
/* ADF4382 REG0030 Map */
|
||||
#define ADF4382_MUTE_NCLK_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_MUTE_RCLK_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_REF_SEL_MSK NO_OS_BIT(5)
|
||||
#define ADF4382_INV_RDBLR_MSK NO_OS_BIT(4)
|
||||
#define ADF4382_RDBLR_DEL_SEL_MSK NO_OS_GENMASK(3, 0)
|
||||
|
||||
/* ADF4382 REG0031 Map */
|
||||
#define ADF4382_SYNC_DEL_MSK NO_OS_GENMASK(7, 5)
|
||||
#define ADF4382_RST_SYS_MSK NO_OS_BIT(4)
|
||||
#define ADF4382_EN_ADC_CLK_MSK NO_OS_BIT(3)
|
||||
#define ADF4382_EN_VCAL_MSK NO_OS_BIT(2)
|
||||
#define ADF4382_CAL_CT_SEL_MSK NO_OS_BIT(1)
|
||||
#define ADF4382_DCLK_MODE_MSK NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG0032 Map */
|
||||
#define ADF4382_SPARE_32_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_BLEED_ADJ_CAL_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_DEL_MODE_MSK NO_OS_BIT(5)
|
||||
#define ADF4382_EN_AUTO_ALIGN_MSK NO_OS_BIT(4)
|
||||
#define ADF4382_PHASE_ADJ_POL_MSK NO_OS_BIT(3)
|
||||
#define ADF4382_EFM3_MODE_MSK NO_OS_GENMASK(2, 0)
|
||||
|
||||
/* ADF4382 REG0033 Map */
|
||||
#define ADF4382_PHASE_ADJUST_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0034 Map */
|
||||
#define ADF4382_PHASE_ADJ_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_DRCLK_DEL_MSK NO_OS_GENMASK(6, 4)
|
||||
#define ADF4382_DNCLK_DEL_MSK NO_OS_GENMASK(3, 1)
|
||||
#define ADF4382_RST_CNTR_MSK NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG0035 Map */
|
||||
#define ADF4382_SPARE_35_MSK NO_OS_GENMASK(7, 6)
|
||||
#define ADF4382_M_VCO_BIAS_MSK NO_OS_GENMASK(5, 0)
|
||||
|
||||
/* ADF4382 REG0036 Map */
|
||||
#define ADF4382_CLKODIV_DB_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_DCLK_DIV_DB_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_SPARE_36_MSK NO_OS_GENMASK(5, 2)
|
||||
#define ADF4382_EN_LUT_GEN_MSK NO_OS_BIT(1)
|
||||
#define ADF4382_EN_LUT_CAL_MSK NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG0037 Map */
|
||||
#define ADF4382_CAL_COUNT_TO_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0038 Map */
|
||||
#define ADF4382_CAL_VTUNE_TO_LSB_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0039 Map */
|
||||
#define ADF4382_O_VCO_DB_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_CAL_VTUNE_TO_MSB_MSK NO_OS_GENMASK(6, 0)
|
||||
|
||||
/* ADF4382 REG003A Map */
|
||||
#define ADF4382_CAL_VCO_TO_LSB_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG003B Map */
|
||||
#define ADF4382_DEL_CTRL_DB_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_CAL_VCO_TO_MSB_MSK NO_OS_GENMASK(6, 0)
|
||||
|
||||
/* ADF4382 REG003C Map */
|
||||
#define ADF4382_CNTR_DIV_WORD_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG003D Map */
|
||||
#define ADF4382_SPARE_3D_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_SYNC_SP_DB_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_CMOS_OV_MSK NO_OS_BIT(5)
|
||||
#define ADF4382_READ_MODE_MSK NO_OS_BIT(4)
|
||||
#define ADF4382_CNTR_DIV_WORD_MSB_MSK NO_OS_GENMASK(3, 0)
|
||||
|
||||
/* ADF4382 REG003E Map */
|
||||
#define ADF4382_ADC_CLK_DIV_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG003F Map */
|
||||
#define ADF4382_EN_ADC_CNV_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_EN_ADC_VTEST_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_ADC_VTEST_SEL_MSK NO_OS_BIT(5)
|
||||
#define ADF4382_ADC_MUX_SEL_MSK NO_OS_BIT(4)
|
||||
#define ADF4382_ADC_F_CONV_MSK NO_OS_BIT(3)
|
||||
#define ADF4382_ADC_C_CONV_MSK NO_OS_BIT(2)
|
||||
#define ADF4382_EN_ADC_MSK NO_OS_BIT(1)
|
||||
#define ADF4382_SPARE_3F_MSK NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG0040 Map */
|
||||
#define ADF4382_EXT_DIV_DEC_SEL_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_ADC_CLK_TEST_SEL_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_MUTE_CLKOUT2_MSK NO_OS_GENMASK(5, 3)
|
||||
#define ADF4382_MUTE_CLKOUT1_MSK NO_OS_GENMASK(2, 0)
|
||||
|
||||
/* ADF4382 REG0041 Map */
|
||||
#define ADF4382_EXT_DIV_MSK NO_OS_GENMASK(7, 5)
|
||||
#define ADF4382_EN_VCO_CAP_TEST_MSK NO_OS_BIT(4)
|
||||
#define ADF4382_EN_CALGEN_CAP_TEST_MSK NO_OS_BIT(3)
|
||||
#define ADF4382_EN_CP_CAP_TEST_MSK NO_OS_BIT(2)
|
||||
#define ADF4382_CAP_TEST_STATE_MSK NO_OS_BIT(1)
|
||||
#define ADF4382_TRANS_LOOP_SEL_MSK NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG0042 Map */
|
||||
#define ADF4382_NDIV_PWRUP_TIMEOUT_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0043 Map */
|
||||
#define ADF4382_CAL_BLEED_FINE_MAX_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0044 Map */
|
||||
#define ADF4382_VCAL_ZERO_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_VPTAT_CALGEN_MSK NO_OS_GENMASK(6, 0)
|
||||
|
||||
/* ADF4382 REG0045 Map */
|
||||
#define ADF4382_SPARE_45_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_VCTAT_CALGEN_MSK NO_OS_GENMASK(6, 0)
|
||||
|
||||
/* ADF4382 REG0046 Map */
|
||||
#define ADF4382_NVMDIN_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0047 Map */
|
||||
#define ADF4382_SPARE_47_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_NVMADDR_MSK NO_OS_GENMASK(6, 3)
|
||||
#define ADF4382_NVMNO_OS_BIT_SEL NO_OS_GENMASK(2, 0)
|
||||
|
||||
/* ADF4382 REG0048 Map */
|
||||
#define ADF4382_TRIM_LATCH_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_NVMTEST_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_NVMPROG_MSK NO_OS_BIT(5)
|
||||
#define ADF4382_NVMRD_MSK NO_OS_BIT(4)
|
||||
#define ADF4382_NVMSTART_MSK NO_OS_BIT(3)
|
||||
#define ADF4382_NVMON_MSK NO_OS_BIT(2)
|
||||
#define ADF4382_MARGIN_MSK NO_OS_GENMASK(1, 0)
|
||||
|
||||
/* ADF4382 REG0049 Map */
|
||||
#define ADF4382_NVMDOUT_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG004A Map */
|
||||
#define ADF4382_SCAN_MODE_CODE_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG004B Map */
|
||||
#define ADF4382_TEMP_OFFSET_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG004C Map */
|
||||
#define ADF4382_SPARE_4C_MSK NO_OS_GENMASK(7, 6)
|
||||
#define ADF4382_TEMP_SLOPE_MSK NO_OS_GENMASK(5, 0)
|
||||
|
||||
/* ADF4382 REG004D Map */
|
||||
#define ADF4382_VCO_FSM_TEST_MUX_MSK NO_OS_GENMASK(7, 5)
|
||||
#define ADF4382_SPARE_4D_MSK NO_OS_GENMASK(4, 3)
|
||||
#define ADF4382_O_VCO_BIAS_MSK NO_OS_BIT(2)
|
||||
#define ADF4382_O_VCO_BAND_MSK NO_OS_BIT(1)
|
||||
#define ADF4382_O_VCO_CORE_MSK NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG004E Map */
|
||||
#define ADF4382_SPARE_4E_MSK NO_OS_GENMASK(7, 5)
|
||||
#define ADF4382_EN_TWO_PASS_CAL_MSK NO_OS_BIT(4)
|
||||
#define ADF4382_TWO_PASS_BAND_START_MSK NO_OS_GENMASK(3, 0)
|
||||
|
||||
/* ADF4382 REG004F Map */
|
||||
#define ADF4382_LUT_SCALE_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0050 Map */
|
||||
#define ADF4382_SPARE0_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0051 Map */
|
||||
#define ADF4382_SPARE1_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0052 Map */
|
||||
#define ADF4382_SYNC_REF_SPARE_MSK NO_OS_GENMASK(7, 4)
|
||||
#define ADF4382_SYNC_MON_DEL_MSK NO_OS_GENMASK(3, 0)
|
||||
|
||||
/* ADF4382 REG0053 Map */
|
||||
#define ADF4382_SPARE_53_MSK NO_OS_BIT(7)
|
||||
#define ADF4382_PD_SYNC_MON_MSK NO_OS_BIT(6)
|
||||
#define ADF4382_SYNC_SEL_MSK NO_OS_BIT(5)
|
||||
#define ADF4382_RST_SYNC_MON_MSK NO_OS_BIT(4)
|
||||
#define ADF4382_SYNC_SH_DEL_MSK NO_OS_GENMASK(3, 0)
|
||||
|
||||
/* ADF4382 REG0054 Map */
|
||||
#define ADF4382_ADC_ST_CNV_MSK NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG0058 Map */
|
||||
#define ADF4382_FSM_BUSY_MSK NO_OS_BIT(1)
|
||||
#define ADF4382_LOCKED_MSK NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG005E Map */
|
||||
#define ADF4382_VCO_BAND_LSB_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG005F Map */
|
||||
#define ADF4382_VCO_CORE_MSK NO_OS_BIT(1)
|
||||
#define ADF4382_VCO_BAND_MSB_MSK NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG0200 Map */
|
||||
#define ADF4382_LUT_WR_ADDR_MSK NO_OS_GENMASK(5, 1)
|
||||
#define ADF4382_O_VCO_LUT_MSK NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG0201 Map */
|
||||
#define ADF4382_M_LUT_BAND_LSB_MSK NO_OS_GENMASK(7, 0)
|
||||
|
||||
/* ADF4382 REG0202 Map */
|
||||
#define ADF4382_M_LUT_N_LSB_MSK NO_OS_GENMASK(7, 2)
|
||||
#define ADF4382_M_LUT_CORE_MSK NO_OS_BIT(1)
|
||||
#define ADF4382_M_LUT_BAND_MSB_MSK NO_OS_BIT(0)
|
||||
|
||||
/* ADF4382 REG0203 Map */
|
||||
#define ADF4382_M_LUT_N_MSB_MSK NO_OS_GENMASK(5, 0)
|
||||
|
||||
#define ADF4382_SPI_3W_CFG(x) (no_os_field_prep(ADF4382_SDO_ACTIVE_MSK, x) | \
|
||||
no_os_field_prep(ADF4382_SDO_ACTIVE_R_MSK, x))
|
||||
|
||||
#define ADF4382_BLEED_MSB_MSK (ADF4382_COARSE_BLEED_MSK | \
|
||||
ADF4382_FINE_BLEED_MSB_MSK)
|
||||
|
||||
#define ADF4382_SPI_SCRATCHPAD_TEST 0x5A
|
||||
|
||||
/* Specifications */
|
||||
#define ADF4382_SPI_WRITE_CMD 0x0
|
||||
#define ADF4382_SPI_READ_CMD 0x8000
|
||||
#define ADF4382_SPI_DUMMY_DATA 0x00
|
||||
#define ADF4382_BUFF_SIZE_BYTES 3
|
||||
#define ADF4382_VCO_FREQ_MIN 11000000000U // 11GHz
|
||||
#define ADF4382_VCO_FREQ_MAX 22000000000U // 22GHz
|
||||
#define ADF4383_VCO_FREQ_MIN 10000000000U // 10GHz
|
||||
#define ADF4383_VCO_FREQ_MAX 20000000000U // 20GHz
|
||||
#define ADF4382A_VCO_FREQ_MIN 11500000000U // 11.5GHz
|
||||
#define ADF4382A_VCO_FREQ_MAX 21000000000U // 21GHz
|
||||
#define ADF4382_MOD1WORD 0x2000000U // 2^25
|
||||
#define ADF4382_MOD2WORD_MAX 0xFFFFFFU // 2^24 - 1
|
||||
#define ADF4382_PHASE_RESYNC_MOD2WORD_MAX 0x1FFFFU // 2^17 - 1
|
||||
#define ADF4382_CHANNEL_SPACING_MAX 78125U
|
||||
#define ADF4382_PFD_FREQ_MAX 625000000U // 625MHz
|
||||
#define ADF4382_PFD_FREQ_FRAC_MAX 250000000U // 250MHz
|
||||
#define ADF4382_PFD_FREQ_MIN 5400000U // 5.4MHz
|
||||
#define ADF4382_DCLK_DIV1_0_MAX 160000000U // 160MHz
|
||||
#define ADF4382_DCLK_DIV1_1_MAX 320000000U // 320MHz
|
||||
#define ADF4382_CLKOUT_DIV_REG_VAL_MAX 4
|
||||
#define ADF4382A_CLKOUT_DIV_REG_VAL_MAX 2
|
||||
|
||||
#define ADF4383_RFOUT_MAX 20000000000U
|
||||
#define ADF4383_RFOUT_MIN 625000000U
|
||||
#define ADF4382_RFOUT_MAX 22000000000U
|
||||
#define ADF4382_RFOUT_MIN 687500000U
|
||||
#define ADF4382A_RFOUT_MAX 21000000000U
|
||||
#define ADF4382A_RFOUT_MIN 2875000000U
|
||||
#define ADF4382_REF_CLK_MAX 5000000000U
|
||||
#define ADF4382_REF_CLK_MIN 10000000
|
||||
#define ADF4382_REF_DIV_MAX 63
|
||||
#define ADF4382_OUT_PWR_MAX 15
|
||||
#define ADF4382_CPI_VAL_MAX 15
|
||||
#define ADF4382_BLEED_WORD_MAX 8191
|
||||
|
||||
#define ADF4382_VPTAT_CALGEN 46
|
||||
#define ADF4382_VCTAT_CALGEN 82
|
||||
#define ADF4382_FASTCAL_VPTAT_CALGEN 30
|
||||
#define ADF4382_FASTCAL_VCTAT_CALGEN 70
|
||||
#define ADF4382_PHASE_BLEED_CNST 2044000
|
||||
#define ADF4382_VCO_CAL_CNT 183
|
||||
#define ADF4382_VCO_CAL_VTUNE 640
|
||||
#define ADF4382_VCO_CAL_ALC 123
|
||||
#define ADF4382_POR_DELAY_US 200
|
||||
#define ADF4382_LKD_DELAY_US 500
|
||||
#define ADF4382_COARSE_BLEED_CONST 180U // 180 microseconds
|
||||
#define ADF4382_FINE_BLEED_CONST_1 512U // 512 microseconds
|
||||
#define ADF4382_FINE_BLEED_CONST_2 250U // 250 microseconds
|
||||
|
||||
#define MHZ MEGA
|
||||
#define S_TO_NS NANO
|
||||
#define PS_TO_S PICO
|
||||
#define NS_TO_PS KHZ_PER_MHZ
|
||||
|
||||
/**
|
||||
* @brief Supported device ids.
|
||||
*/
|
||||
enum adf4382_dev_id {
|
||||
ID_ADF4382,
|
||||
ID_ADF4382A,
|
||||
ID_ADF4383,
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct adf4382_init_param
|
||||
* @brief ADF4382 Initialization Parameters structure.
|
||||
*/
|
||||
struct adf4382_init_param {
|
||||
/** SPI Initialization parameters */
|
||||
struct no_os_spi_init_param *spi_init;
|
||||
bool spi_3wire_en;
|
||||
bool cmos_3v3;
|
||||
uint64_t ref_freq_hz;
|
||||
uint64_t freq;
|
||||
bool ref_doubler_en;
|
||||
uint8_t ref_div;
|
||||
uint8_t cp_i;
|
||||
uint16_t bleed_word;
|
||||
uint8_t ld_count;
|
||||
uint8_t en_lut_gen;
|
||||
uint8_t en_lut_cal;
|
||||
enum adf4382_dev_id id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct adf4382_dev
|
||||
* @brief ADF4382 Device Descriptor.
|
||||
*/
|
||||
struct adf4382_dev {
|
||||
/** SPI Descriptor */
|
||||
struct no_os_spi_desc *spi_desc;
|
||||
bool spi_3wire_en;
|
||||
bool cmos_3v3;
|
||||
uint64_t ref_freq_hz;
|
||||
uint64_t freq;
|
||||
bool ref_doubler_en;
|
||||
uint8_t ref_div;
|
||||
uint8_t cp_i;
|
||||
uint16_t bleed_word;
|
||||
uint8_t ld_count;
|
||||
uint32_t phase_adj;
|
||||
uint8_t en_lut_gen;
|
||||
uint8_t en_lut_cal;
|
||||
uint64_t vco_max;
|
||||
uint64_t vco_min;
|
||||
uint64_t freq_max;
|
||||
uint64_t freq_min;
|
||||
uint8_t clkout_div_reg_val_max;
|
||||
// N_INT variable to trigger auto calibration
|
||||
uint16_t n_int;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct reg_sequence
|
||||
* @brief ADF4382 register format structure for default values
|
||||
*/
|
||||
struct reg_sequence {
|
||||
uint16_t reg;
|
||||
uint8_t val;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct adf4382_reg_defaults
|
||||
* @brief ADF4382 register initialization
|
||||
*/
|
||||
static const struct reg_sequence adf4382_reg_defaults[] = {
|
||||
{ 0x000, 0x18 },
|
||||
{ 0x00a, 0xA5 },
|
||||
{ 0x200, 0x00 },
|
||||
{ 0x201, 0x00 },
|
||||
{ 0x202, 0x00 },
|
||||
{ 0x203, 0x00 },
|
||||
{ 0x203, 0x00 },
|
||||
{ 0x203, 0x00 },
|
||||
{ 0x100, 0x25 },
|
||||
{ 0x101, 0x3F },
|
||||
{ 0x102, 0x3F },
|
||||
{ 0x103, 0x3F },
|
||||
{ 0x104, 0x3F },
|
||||
{ 0x105, 0x3F },
|
||||
{ 0x106, 0x3F },
|
||||
{ 0x107, 0x3F },
|
||||
{ 0x108, 0x3F },
|
||||
{ 0x109, 0x25 },
|
||||
{ 0x10A, 0x25 },
|
||||
{ 0x10B, 0x3F },
|
||||
{ 0x10C, 0x3F },
|
||||
{ 0x10D, 0x3F },
|
||||
{ 0x10E, 0x3F },
|
||||
{ 0x10F, 0x3F },
|
||||
{ 0x110, 0x3F },
|
||||
{ 0x111, 0x3F },
|
||||
{ 0x054, 0x00 },
|
||||
{ 0x053, 0x45 },
|
||||
{ 0x052, 0x00 },
|
||||
{ 0x051, 0x00 },
|
||||
{ 0x050, 0x00 },
|
||||
{ 0x04f, 0x08 },
|
||||
{ 0x04e, 0x06 },
|
||||
{ 0x04d, 0x00 },
|
||||
{ 0x04c, 0x2B },
|
||||
{ 0x04b, 0x5D },
|
||||
{ 0x04a, 0x00 },
|
||||
{ 0x048, 0x00 },
|
||||
{ 0x047, 0x00 },
|
||||
{ 0x046, 0x00 },
|
||||
{ 0x045, 0x52 },
|
||||
{ 0x044, 0x2E },
|
||||
{ 0x043, 0xB8 },
|
||||
{ 0x042, 0x01 },
|
||||
{ 0x041, 0x00 },
|
||||
{ 0x040, 0x00 },
|
||||
{ 0x03f, 0x82 },
|
||||
{ 0x03e, 0x4E },
|
||||
{ 0x03c, 0x00 },
|
||||
{ 0x03b, 0x00 },
|
||||
{ 0x03a, 0xFA },
|
||||
{ 0x039, 0x80 },
|
||||
{ 0x038, 0x71 },
|
||||
{ 0x037, 0x82 },
|
||||
{ 0x036, 0xC0 },
|
||||
{ 0x035, 0x00 },
|
||||
{ 0x034, 0x36 },
|
||||
{ 0x033, 0x00 },
|
||||
{ 0x032, 0x40 },
|
||||
{ 0x031, 0x63 },
|
||||
{ 0x030, 0x0F },
|
||||
{ 0x02f, 0x3F },
|
||||
{ 0x02e, 0x00 },
|
||||
{ 0x02d, 0xF1 },
|
||||
{ 0x02c, 0x0E },
|
||||
{ 0x02b, 0x01 },
|
||||
{ 0x02a, 0x30 },
|
||||
{ 0x029, 0x09 },
|
||||
{ 0x028, 0x00 },
|
||||
{ 0x027, 0xF0 },
|
||||
{ 0x026, 0x00 },
|
||||
{ 0x025, 0x01 },
|
||||
{ 0x024, 0x01 },
|
||||
{ 0x023, 0x00 },
|
||||
{ 0x022, 0x00 },
|
||||
{ 0x021, 0x00 },
|
||||
{ 0x020, 0xC1 },
|
||||
{ 0x01f, 0x0F },
|
||||
{ 0x01e, 0x20 },
|
||||
{ 0x01d, 0x00 },
|
||||
{ 0x01c, 0x00 },
|
||||
{ 0x01b, 0x00 },
|
||||
{ 0x01a, 0x00 },
|
||||
{ 0x019, 0x00 },
|
||||
{ 0x018, 0x00 },
|
||||
{ 0x017, 0x00 },
|
||||
{ 0x016, 0x00 },
|
||||
{ 0x015, 0x06 },
|
||||
{ 0x014, 0x00 },
|
||||
{ 0x013, 0x00 },
|
||||
{ 0x012, 0x00 },
|
||||
{ 0x011, 0x00 },
|
||||
{ 0x010, 0x50 },
|
||||
};
|
||||
|
||||
/** ADF4382 SPI write */
|
||||
int adf4382_spi_write(struct adf4382_dev *dev, uint16_t reg_addr, uint8_t data);
|
||||
|
||||
/** ADF4382 SPI Read */
|
||||
int adf4382_spi_read(struct adf4382_dev *dev, uint16_t reg_addr, uint8_t *data);
|
||||
|
||||
/** ADF4382 updates a bit in the register space over SPI */
|
||||
int adf4382_spi_update_bits(struct adf4382_dev *dev, uint16_t reg_addr,
|
||||
uint8_t mask, uint8_t data);
|
||||
|
||||
/** ADF4382 Register dump */
|
||||
int adf4382_reg_dump(struct adf4382_dev *dev);
|
||||
|
||||
/** ADF4382 Set reference frequency attribute */
|
||||
int adf4382_set_ref_clk(struct adf4382_dev *dev, uint64_t val);
|
||||
|
||||
/** ADF4382 Get reference frequency attribute */
|
||||
int adf4382_get_ref_clk(struct adf4382_dev *dev, uint64_t *val);
|
||||
|
||||
/** ADF4382 Set reference doubler attribute */
|
||||
int adf4382_set_en_ref_doubler(struct adf4382_dev *dev, bool en);
|
||||
|
||||
/** ADF4382 Get reference doubler attribute */
|
||||
int adf4382_get_en_ref_doubler(struct adf4382_dev *dev, bool *en);
|
||||
|
||||
/** ADF4382 Set reference divider attribute */
|
||||
int adf4382_set_ref_div(struct adf4382_dev *dev, int32_t div);
|
||||
|
||||
/** ADF4382 Get reference divider attribute */
|
||||
int adf4382_get_ref_div(struct adf4382_dev *dev, int32_t *div);
|
||||
|
||||
/** ADF4382 Set charge pump current attribute */
|
||||
int adf4382_set_cp_i(struct adf4382_dev *dev, int32_t reg_val);
|
||||
|
||||
/** ADF4382 Get charge pump current attribute */
|
||||
int adf4382_get_cp_i(struct adf4382_dev *dev, int32_t *reg_val);
|
||||
|
||||
/** ADF4382 Set bleed current attribute */
|
||||
int adf4382_set_bleed_word(struct adf4382_dev *dev, int32_t word);
|
||||
|
||||
/** ADF4382 Get bleed current attribute */
|
||||
int adf4382_get_bleed_word(struct adf4382_dev *dev, int32_t *word);
|
||||
|
||||
/** ADF4382 Set output frequency attribute */
|
||||
int adf4382_set_rfout(struct adf4382_dev *dev, uint64_t val);
|
||||
|
||||
/** ADF4382 Get output frequency attribute */
|
||||
int adf4382_get_rfout(struct adf4382_dev *dev, uint64_t *val);
|
||||
|
||||
/** ADF4382 Set output power attributes */
|
||||
int adf4382_set_out_power(struct adf4382_dev *dev, uint8_t ch, int32_t pwr);
|
||||
|
||||
/** ADF4382 Get output power attributes */
|
||||
int adf4382_get_out_power(struct adf4382_dev *dev, uint8_t ch, int32_t *pwr);
|
||||
|
||||
/** ADF4382 Set channel enable attributes */
|
||||
int adf4382_set_en_chan(struct adf4382_dev *dev, uint8_t ch, bool en);
|
||||
|
||||
/** ADF4382 Get channel enable attributes */
|
||||
int adf4382_get_en_chan(struct adf4382_dev *dev, uint8_t ch, bool *en);
|
||||
|
||||
/** ADF4382 Sets frequency */
|
||||
int adf4382_set_freq(struct adf4382_dev *dev);
|
||||
|
||||
/** ADF4382 Set fast calibration attributes */
|
||||
int adf4382_set_en_fast_calibration(struct adf4382_dev *dev, bool en_fast_cal);
|
||||
|
||||
/** ADF4382 Set fast calibration LUT calibration attributes */
|
||||
int adf4382_set_en_lut_calibration(struct adf4382_dev *dev, bool en_lut_cal);
|
||||
|
||||
/** ADF4382 Get Fast Calibration LUT Calibration attributes */
|
||||
int adf4382_get_en_lut_calibration(struct adf4382_dev *dev, bool *en);
|
||||
|
||||
/** ADF4382 Set Output Frequency without writing the Ndiv Register */
|
||||
int adf4382_set_change_freq(struct adf4382_dev *dev);
|
||||
|
||||
/** ADF4382 Get Change Output Frequency attribute value */
|
||||
int adf4382_get_change_rfout(struct adf4382_dev *dev, uint64_t *val);
|
||||
|
||||
/** ADF4382 Set Change Output Frequency attribute value */
|
||||
int adf4382_set_change_rfout(struct adf4382_dev *dev, uint64_t val);
|
||||
|
||||
/** ADF4382 Set the NDIV register attribute value */
|
||||
int adf4382_set_start_calibration(struct adf4382_dev *dev);
|
||||
|
||||
/** ADF4382 Get the NDIV register attribute value as 0 */
|
||||
int adf4382_get_start_calibration(struct adf4382_dev *dev, bool *start_cal);
|
||||
|
||||
/** ADF4382 Sets Phase adjustment */
|
||||
int adf4382_set_phase_adjust(struct adf4382_dev *dev, uint32_t phase_ps);
|
||||
|
||||
/** ADF4382 Sets Phase adjustment polarity*/
|
||||
int adf4382_set_phase_pol(struct adf4382_dev *dev, bool polarity);
|
||||
|
||||
/** ADF4382 Gets Phase adjustment polarity*/
|
||||
int adf4382_get_phase_pol(struct adf4382_dev *dev, bool *polarity);
|
||||
|
||||
/** ADF4382 Set EZSYNC feature attributes */
|
||||
int adf4382_set_ezsync_setup(struct adf4382_dev *dev, bool sync);
|
||||
|
||||
/** ADF4382 Set Timed SYNC feature attributes */
|
||||
int adf4382_set_timed_sync_setup(struct adf4382_dev *dev, bool sync);
|
||||
|
||||
/** ADF4382 Get EZSYNC and Timed SYNC feature attributes */
|
||||
int adf4382_get_phase_sync_setup(struct adf4382_dev *dev, bool *en);
|
||||
|
||||
/** ADF4382 Set sw_sync attribute */
|
||||
int adf4382_set_sw_sync(struct adf4382_dev *dev, bool sw_sync);
|
||||
|
||||
/** ADF4382 Get sw_sync attribute */
|
||||
int adf4382_get_sw_sync(struct adf4382_dev *dev, bool *sw_sync);
|
||||
|
||||
/** ADF4382 Initialization */
|
||||
int adf4382_init(struct adf4382_dev **device,
|
||||
struct adf4382_init_param *init_param);
|
||||
|
||||
/** ADF4382 Remove */
|
||||
int adf4382_remove(struct adf4382_dev *dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,43 @@
|
||||
#ifndef HARDWARE_CONFIG_H
|
||||
|
||||
#define HARDWARE_CONFIG_H
|
||||
|
||||
#include "stm32f7xx_hal.h"
|
||||
|
||||
#define GPIO_VR GPIOB
|
||||
#define EN_32 GPIO_PIN_14 //Active High
|
||||
#define EN_42 GPIO_PIN_15 //Active High
|
||||
|
||||
#define GPIO_si5351 GPIOB
|
||||
#define SI5351_CLK_EN GPIO_PIN_4 //Active Low
|
||||
#define SI5351_SS_EN GPIO_PIN_5 //Active High (Spread Spectrum)
|
||||
|
||||
#define GPIO_ADF GPIOD
|
||||
#define ADF_CS GPIO_PIN_0 //Active Low
|
||||
#define ADF_CE GPIO_PIN_1 //Active High (Chip Enable)
|
||||
#define ADF_DELSTR GPIO_PIN_2 //Delay Strobe/ 1=adjustment needed/ adjustment is made after GPIO_PIN_ssing from 1 to 0
|
||||
#define ADF_DELADJ GPIO_PIN_3 // Delay Adjustment/ 0=ensures that delay of RF is reduced when ADF_DELSTR is asserted/ 0!=1
|
||||
|
||||
#define GPIO_LED GPIOD
|
||||
#define LED_1 GPIO_PIN_10
|
||||
#define LED_2 GPIO_PIN_11
|
||||
#define LED_3 GPIO_PIN_12
|
||||
#define LED_4 GPIO_PIN_13
|
||||
|
||||
#define GPIO_ADAR GPIOA
|
||||
#define CS_ADAR_1 GPIO_PIN_8
|
||||
#define CS_ADAR_2 GPIO_PIN_9
|
||||
#define CS_ADAR_3 GPIO_PIN_10
|
||||
#define CS_ADAR_4 GPIO_PIN_11
|
||||
|
||||
#define GPIO_DIG GPIOC
|
||||
#define DIG_0 GPIO_PIN_0 // 0 = RX mode, 1 = TX mode
|
||||
#define DIG_1 GPIO_PIN_1 // Send RX ADC start frame of (83x83) to FT2232HQ_FPGA
|
||||
#define DIG_2 GPIO_PIN_2 // Enable = 1 / Disable = 0 RX mixer
|
||||
#define DIG_3 GPIO_PIN_3 // Enable = 1 / Disable = 0 RX mixer
|
||||
#define DIG_4 GPIO_PIN_4 //
|
||||
#define DIG_5 GPIO_PIN_5
|
||||
#define DIG_6 GPIO_PIN_6
|
||||
#define DIG_7 GPIO_PIN_7
|
||||
|
||||
#endif // HARDWARE_CONFIG_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,143 @@
|
||||
/***************************************************************************//**
|
||||
* @file iio.h
|
||||
* @brief Header file of iio
|
||||
* @author Cristian Pop (cristian.pop@analog.com)
|
||||
* @author Mihail Chindris (mihail.chindris@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2013(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef IIO_H_
|
||||
#define IIO_H_
|
||||
|
||||
#include "iio_types.h"
|
||||
#include "no_os_uart.h"
|
||||
#if defined(NO_OS_NETWORKING) || defined(NO_OS_LWIP_NETWORKING)
|
||||
#include "tcp_socket.h"
|
||||
#endif
|
||||
|
||||
enum physical_link_type {
|
||||
USE_UART,
|
||||
USE_LOCAL_BACKEND,
|
||||
USE_NETWORK
|
||||
};
|
||||
|
||||
struct iio_desc;
|
||||
|
||||
struct iio_device_init {
|
||||
char *name;
|
||||
void *dev;
|
||||
struct iio_device *dev_descriptor;
|
||||
/*
|
||||
* IIO buffer implementation can use a user provided buffer in raw_buf.
|
||||
* If raw_buf is NULL and iio_device has buffer callback function set,
|
||||
* it will allocate memory for it when needed.
|
||||
*/
|
||||
int8_t *raw_buf;
|
||||
/* Length of raw_buf */
|
||||
uint32_t raw_buf_len;
|
||||
/* If set, trigger will be linked to this device */
|
||||
char *trigger_id;
|
||||
};
|
||||
|
||||
struct iio_trigger_init {
|
||||
char *name;
|
||||
void *trig;
|
||||
struct iio_trigger *descriptor;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct iio_ctx_attr
|
||||
* @brief Structure holding the context attribute members
|
||||
*/
|
||||
struct iio_ctx_attr {
|
||||
/** Attribute name */
|
||||
const char *name;
|
||||
/** Attribute value */
|
||||
const char *value;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct iio_local_backend
|
||||
* @brief Structure holding the local backend init parameters
|
||||
*/
|
||||
struct iio_local_backend {
|
||||
int(*local_backend_event_read)(void *conn, uint8_t *buf, uint32_t len);
|
||||
int(*local_backend_event_write)(void *conn, uint8_t *buf, uint32_t len);
|
||||
char *local_backend_buff;
|
||||
uint32_t local_backend_buff_len;
|
||||
};
|
||||
|
||||
struct iio_init_param {
|
||||
enum physical_link_type phy_type;
|
||||
union {
|
||||
struct no_os_uart_desc *uart_desc;
|
||||
#if defined(NO_OS_NETWORKING) || defined(NO_OS_LWIP_NETWORKING)
|
||||
struct tcp_socket_init_param *tcp_socket_init_param;
|
||||
#endif
|
||||
};
|
||||
struct iio_local_backend *local_backend;
|
||||
struct iio_ctx_attr *ctx_attrs;
|
||||
uint32_t nb_ctx_attr;
|
||||
struct iio_device_init *devs;
|
||||
uint32_t nb_devs;
|
||||
struct iio_trigger_init *trigs;
|
||||
uint32_t nb_trigs;
|
||||
};
|
||||
|
||||
/* Set communication ops and read/write ops. */
|
||||
int iio_init(struct iio_desc **desc, struct iio_init_param *init_param);
|
||||
/* Free the resources allocated by iio_init(). */
|
||||
int iio_remove(struct iio_desc *desc);
|
||||
/* Execut an iio step. */
|
||||
int iio_step(struct iio_desc *desc);
|
||||
/* Signal iio that a trigger has been triggered.
|
||||
* This will be called in interrupt context. An application callback will be
|
||||
called in interrupt context if trigger is synchronous with the interrupt
|
||||
(is_synchronous = true) or will be called from iio_step if trigger is
|
||||
asynchronous (is_synchronous = false) */
|
||||
int iio_process_trigger_type(struct iio_desc *desc, char *trigger_name);
|
||||
|
||||
int32_t iio_parse_value(char *buf, enum iio_val fmt,
|
||||
int32_t *val, int32_t *val2);
|
||||
int iio_format_value(char *buf, uint32_t len, enum iio_val fmt,
|
||||
int32_t size, int32_t *vals);
|
||||
|
||||
/* DMA buffer functions. */
|
||||
/* Get buffer addr where to write iio_buffer.size bytes */
|
||||
int iio_buffer_get_block(struct iio_buffer *buffer, void **addr);
|
||||
/* To be called to mark last iio_buffer_read as done */
|
||||
int iio_buffer_block_done(struct iio_buffer *buffer);
|
||||
|
||||
/* Trigger buffer functions. */
|
||||
/* Write to buffer iio_buffer.bytes_per_scan bytes from data */
|
||||
int iio_buffer_push_scan(struct iio_buffer *buffer, void *data);
|
||||
/* Read from buffer iio_buffer.bytes_per_scan bytes into data */
|
||||
int iio_buffer_pop_scan(struct iio_buffer *buffer, void *data);
|
||||
|
||||
#endif /* IIO_H_ */
|
||||
@@ -0,0 +1,733 @@
|
||||
/***************************************************************************//**
|
||||
* @file iio_adf4382.c
|
||||
* @brief Implementation of IIO ADF4382 Driver.
|
||||
* @authors CHegbeli (ciprian.hegbeli@analog.com)
|
||||
* Jude Osemene (jude.osemene@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2024(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include "no_os_error.h"
|
||||
#include "no_os_util.h"
|
||||
#include "iio_adf4382.h"
|
||||
#include "adf4382.h"
|
||||
#include "no_os_alloc.h"
|
||||
|
||||
/**
|
||||
* @brief Supported charge pump currents
|
||||
*/
|
||||
static const int ci_table[16][2] = {
|
||||
{0, 700000},
|
||||
{0, 900000},
|
||||
{1, 100000},
|
||||
{1, 300000},
|
||||
{1, 500000},
|
||||
{1, 900000},
|
||||
{2, 300000},
|
||||
{2, 700000},
|
||||
{3, 100000},
|
||||
{3, 900000},
|
||||
{4, 700000},
|
||||
{5, 500000},
|
||||
{6, 300000},
|
||||
{7, 900000},
|
||||
{9, 500000},
|
||||
{11, 100000}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Helper function to read a pair of values in a table with 2 elements.
|
||||
* @param tb - Input table.
|
||||
* @param size - Size of the table.
|
||||
* @param val1 - The first value to be found.
|
||||
* @param val2 - The second value to be found.
|
||||
* @return i - The index of the pair if found or an error if there is no
|
||||
* pair of values in the table.
|
||||
*/
|
||||
static int adf4382_iio_find_2d_row(const int (*tbl)[2], const int size,
|
||||
const int val1, const int val2)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (tbl[i][0] == val1 && tbl[i][1] == val2)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wrapper for reading adf4382 register.
|
||||
* @param dev - The iio device structure.
|
||||
* @param reg - Address of the register to be read from.
|
||||
* @param readval - Read data.
|
||||
* @return - Result of the reading procedure.
|
||||
*/
|
||||
static int adf4382_iio_read_reg(struct adf4382_iio_dev *dev, uint32_t reg,
|
||||
uint32_t *readval)
|
||||
{
|
||||
uint8_t tmp;
|
||||
int ret;
|
||||
|
||||
ret = adf4382_spi_read(dev->adf4382_dev, (uint16_t)reg, &tmp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*readval = tmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wrapper for writing adf4382 register.
|
||||
* @param dev - The iio device structure.
|
||||
* @param reg - Address of the register to be written to.
|
||||
* @param writeval - Data to be written.
|
||||
* @return - Result of the writing procedure.
|
||||
*/
|
||||
static int adf4382_iio_write_reg(struct adf4382_iio_dev *dev, uint32_t reg,
|
||||
uint32_t writeval)
|
||||
{
|
||||
return adf4382_spi_write(dev->adf4382_dev, (uint16_t)reg,
|
||||
(uint8_t)writeval);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles the read request for the device attributes.
|
||||
* @param dev - The iio device structure.
|
||||
* @param buf - Command buffer to be filled with requested data.
|
||||
* @param len - Length of the received command buffer in bytes.
|
||||
* @param channel - Command channel info.
|
||||
* @param priv - Command attribute id.
|
||||
* @return - The size of the read data in case of success, error code
|
||||
* otherwise.
|
||||
*/
|
||||
static int adf4382_iio_read_dev_attr(void *dev, char *buf, uint32_t len,
|
||||
const struct iio_ch_info *channel,
|
||||
intptr_t priv)
|
||||
{
|
||||
struct adf4382_iio_dev *iio_adf4382 = (struct adf4382_iio_dev *)dev;
|
||||
struct adf4382_dev *adf4382;
|
||||
int32_t val = -EINVAL;
|
||||
uint64_t val_64 = 0;
|
||||
int32_t val_b[2];
|
||||
char buffer[5];
|
||||
int32_t cp_i;
|
||||
uint8_t i;
|
||||
bool en;
|
||||
int ret;
|
||||
|
||||
if (!iio_adf4382)
|
||||
return -EINVAL;
|
||||
|
||||
adf4382 = iio_adf4382->adf4382_dev;
|
||||
|
||||
if (!adf4382)
|
||||
return -EINVAL;
|
||||
|
||||
switch (priv) {
|
||||
case ADF4382_IIO_DEV_ATTR_REF_FREQ:
|
||||
ret = adf4382_get_ref_clk(adf4382, &val_64);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = snprintf(buf, len, "%"PRIu64, val_64);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_BLEED_CURRENT:
|
||||
ret = adf4382_get_bleed_word(adf4382, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iio_format_value(buf, len, IIO_VAL_INT, 1, &val);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_CHARGE_PUMP_CURRENT:
|
||||
ret = adf4382_get_cp_i(adf4382, &cp_i);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val_b[0] = ci_table[cp_i][0];
|
||||
val_b[1] = ci_table[cp_i][1];
|
||||
ret = iio_format_value(buf, len, IIO_VAL_INT_PLUS_MICRO, 2, val_b);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_CHARGE_PUMP_AVAILABLE:
|
||||
strcpy(buf, "");
|
||||
for (i = 0; i < NO_OS_ARRAY_SIZE(ci_table); i++) {
|
||||
val_b[0] = ci_table[i][0];
|
||||
val_b[1] = ci_table[i][1];
|
||||
iio_format_value(buffer, len, IIO_VAL_INT_PLUS_MICRO, 2,
|
||||
val_b);
|
||||
strcat(buf, buffer);
|
||||
if (i < NO_OS_ARRAY_SIZE(ci_table) - 1)
|
||||
strcat(buf, " ");
|
||||
}
|
||||
ret = strlen(buf);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_REF_DIVIDER:
|
||||
ret = adf4382_get_ref_div(adf4382, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iio_format_value(buf, len, IIO_VAL_INT, 1, &val);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_REF_DOUBLER_EN:
|
||||
ret = adf4382_get_en_ref_doubler(adf4382, &en);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = en;
|
||||
ret = iio_format_value(buf, len, IIO_VAL_INT, 1, &val);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_FASTCAL_EN:
|
||||
ret = adf4382_get_en_lut_calibration(adf4382, &en);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = en;
|
||||
ret = iio_format_value(buf, len, IIO_VAL_INT, 1, &val);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_FASTCAL_LUT_EN:
|
||||
ret = adf4382_get_en_lut_calibration(adf4382, &en);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = en;
|
||||
ret = iio_format_value(buf, len, IIO_VAL_INT, 1, &val);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_FASTCAL_CHANGE_FREQ:
|
||||
ret = adf4382_get_change_rfout(adf4382, &val_64);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = snprintf(buf, len, "%"PRIu64, val_64);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_FASTCAL_START_CALIBRATION:
|
||||
ret = adf4382_get_start_calibration(adf4382, &en);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = en;
|
||||
ret = iio_format_value(buf, len, IIO_VAL_INT, 1, &val);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_SW_SYNC:
|
||||
ret = adf4382_get_sw_sync(adf4382, &en);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = en;
|
||||
ret = iio_format_value(buf, len, IIO_VAL_INT, 1, &val);
|
||||
break;
|
||||
case ADF4382_IIO_DEV_ATTR_EZ_SYNC:
|
||||
ret = adf4382_get_phase_sync_setup(adf4382, &en);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = en;
|
||||
ret = iio_format_value(buf, len, IIO_VAL_INT, 1, &val);
|
||||
break;
|
||||
case ADF4382_IIO_DEV_ATTR_TIMED_SYNC:
|
||||
ret = adf4382_get_phase_sync_setup(adf4382, &en);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = en;
|
||||
ret = iio_format_value(buf, len, IIO_VAL_INT, 1, &val);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Handles the write request for the device attributes.
|
||||
* @param dev - The iio device structure.
|
||||
* @param buf - Command buffer to be filled with requested data.
|
||||
* @param len - Length of the received command buffer in bytes.
|
||||
* @param channel - Command channel info.
|
||||
* @param priv - Command attribute id.
|
||||
* @return - The size of the read data in case of success, error code
|
||||
* otherwise.
|
||||
*/
|
||||
static int adf4382_iio_write_dev_attr(void *dev, char *buf, uint32_t len,
|
||||
const struct iio_ch_info *channel,
|
||||
intptr_t priv)
|
||||
{
|
||||
struct adf4382_iio_dev *iio_adf4382 = (struct adf4382_iio_dev *)dev;
|
||||
struct adf4382_dev *adf4382;
|
||||
int32_t val = -EINVAL;
|
||||
uint64_t val_64 = 0;
|
||||
int32_t val_b[2];
|
||||
bool en;
|
||||
int8_t index;
|
||||
int ret;
|
||||
|
||||
if (!iio_adf4382)
|
||||
return -EINVAL;
|
||||
|
||||
adf4382 = iio_adf4382->adf4382_dev;
|
||||
|
||||
if (!adf4382)
|
||||
return -EINVAL;
|
||||
|
||||
switch (priv) {
|
||||
case ADF4382_IIO_DEV_ATTR_REF_FREQ:
|
||||
sscanf(buf, "%"PRIu64, &val_64);
|
||||
ret = adf4382_set_ref_clk(adf4382, val_64);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_BLEED_CURRENT:
|
||||
iio_parse_value(buf, IIO_VAL_INT, &val, NULL);
|
||||
ret = adf4382_set_bleed_word(adf4382, val);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_CHARGE_PUMP_CURRENT:
|
||||
iio_parse_value(buf, IIO_VAL_INT_PLUS_MICRO, &val_b[0], &val_b[1]);
|
||||
|
||||
index = adf4382_iio_find_2d_row(ci_table, NO_OS_ARRAY_SIZE(ci_table),
|
||||
val_b[0], val_b[1]);
|
||||
if (index < 0)
|
||||
return index;
|
||||
|
||||
ret = adf4382_set_cp_i(adf4382, index);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_REF_DIVIDER:
|
||||
iio_parse_value(buf, IIO_VAL_INT, &val, NULL);
|
||||
ret = adf4382_set_ref_div(adf4382, val);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_REF_DOUBLER_EN:
|
||||
iio_parse_value(buf, IIO_VAL_INT, &val, NULL);
|
||||
|
||||
en = val;
|
||||
ret = adf4382_set_en_ref_doubler(adf4382, val);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_FASTCAL_EN:
|
||||
iio_parse_value(buf, IIO_VAL_INT, &val, NULL);
|
||||
|
||||
en = val;
|
||||
ret = adf4382_set_en_fast_calibration(adf4382, en);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_FASTCAL_LUT_EN:
|
||||
iio_parse_value(buf, IIO_VAL_INT, &val, NULL);
|
||||
|
||||
en = val;
|
||||
ret = adf4382_set_en_lut_calibration(adf4382, en);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_FASTCAL_CHANGE_FREQ:
|
||||
sscanf(buf, "%"PRIu64, &val_64);
|
||||
ret = adf4382_set_change_rfout(adf4382, val_64);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_FASTCAL_START_CALIBRATION:
|
||||
iio_parse_value(buf, IIO_VAL_INT, &val, NULL);
|
||||
|
||||
if (!val)
|
||||
return 0;
|
||||
|
||||
ret = adf4382_set_start_calibration(adf4382);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_SW_SYNC:
|
||||
iio_parse_value(buf, IIO_VAL_INT, &val, NULL);
|
||||
|
||||
en = val;
|
||||
ret = adf4382_set_sw_sync(adf4382, en);
|
||||
break;
|
||||
case ADF4382_IIO_DEV_ATTR_EZ_SYNC:
|
||||
iio_parse_value(buf, IIO_VAL_INT, &val, NULL);
|
||||
|
||||
en = val;
|
||||
ret = adf4382_set_ezsync_setup(adf4382, en);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_DEV_ATTR_TIMED_SYNC:
|
||||
iio_parse_value(buf, IIO_VAL_INT, &val, NULL);
|
||||
|
||||
en = val;
|
||||
ret = adf4382_set_timed_sync_setup(adf4382, en);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles the read request for the channel attributes.
|
||||
* @param dev - The iio device structure.
|
||||
* @param buf - Command buffer to be filled with requested data.
|
||||
* @param len - Length of the received command buffer in bytes.
|
||||
* @param channel - Command channel info.
|
||||
* @param priv - Command attribute id.
|
||||
* @return - The size of the read data in case of success, error code
|
||||
* otherwise.
|
||||
*/
|
||||
static int adf4382_iio_read_chan_attr(void *dev, char *buf, uint32_t len,
|
||||
const struct iio_ch_info *channel,
|
||||
intptr_t priv)
|
||||
{
|
||||
struct adf4382_iio_dev *iio_adf4382 = (struct adf4382_iio_dev *)dev;
|
||||
struct adf4382_dev *adf4382;
|
||||
int32_t val = -EINVAL;
|
||||
uint64_t val_64 = 0;
|
||||
bool en, pol;
|
||||
int ret;
|
||||
|
||||
if (!iio_adf4382)
|
||||
return -EINVAL;
|
||||
|
||||
adf4382 = iio_adf4382->adf4382_dev;
|
||||
|
||||
if (!adf4382)
|
||||
return -EINVAL;
|
||||
|
||||
switch (priv) {
|
||||
case ADF4382_IIO_CH_ATTR_EN:
|
||||
ret = adf4382_get_en_chan(adf4382, channel->ch_num, &en);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = en;
|
||||
ret = iio_format_value(buf, len, IIO_VAL_INT, 1, &val);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_CH_ATTR_FREQ:
|
||||
ret = adf4382_get_rfout(adf4382, &val_64);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = snprintf(buf, len, "%"PRIu64, val_64);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_CH_ATTR_OPWR:
|
||||
ret = adf4382_get_out_power(adf4382, channel->ch_num, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iio_format_value(buf, len, IIO_VAL_INT, 1, &val);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_CH_ATTR_PHASE_ADJ:
|
||||
val = adf4382->phase_adj;
|
||||
ret = adf4382_get_phase_pol(adf4382, &pol);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (pol)
|
||||
val *= -1;
|
||||
|
||||
ret = iio_format_value(buf, len, IIO_VAL_INT, 1, &val);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles the write request for the channel attributes.
|
||||
* @param dev - The iio device structure.
|
||||
* @param buf - Command buffer to be filled with requested data.
|
||||
* @param len - Length of the received command buffer in bytes.
|
||||
* @param channel - Command channel info.
|
||||
* @param priv - Command attribute id.
|
||||
* @return - The size of the read data in case of success, error code
|
||||
* otherwise.
|
||||
*/
|
||||
static int adf4382_iio_write_chan_attr(void *dev, char *buf, uint32_t len,
|
||||
const struct iio_ch_info *channel,
|
||||
intptr_t priv)
|
||||
{
|
||||
struct adf4382_iio_dev *iio_adf4382 = (struct adf4382_iio_dev *)dev;
|
||||
struct adf4382_dev *adf4382;
|
||||
int32_t val = -EINVAL;
|
||||
uint64_t val_64 = 0;
|
||||
bool en;
|
||||
int ret;
|
||||
|
||||
if (!iio_adf4382)
|
||||
return -EINVAL;
|
||||
|
||||
adf4382 = iio_adf4382->adf4382_dev;
|
||||
|
||||
if (!adf4382)
|
||||
return -EINVAL;
|
||||
|
||||
switch (priv) {
|
||||
case ADF4382_IIO_CH_ATTR_EN:
|
||||
iio_parse_value(buf, IIO_VAL_INT, &val, NULL);
|
||||
|
||||
en = val;
|
||||
ret = adf4382_set_en_chan(adf4382, channel->ch_num, en);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_CH_ATTR_FREQ:
|
||||
sscanf(buf, "%"PRIu64, &val_64);
|
||||
|
||||
ret = adf4382_set_rfout(adf4382, val_64);
|
||||
break;
|
||||
|
||||
case ADF4382_IIO_CH_ATTR_PHASE_ADJ:
|
||||
iio_parse_value(buf, IIO_VAL_INT, &val, NULL);
|
||||
if (val < 0)
|
||||
ret = adf4382_set_phase_pol(adf4382, 1);
|
||||
else
|
||||
ret = adf4382_set_phase_pol(adf4382, 0);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = abs(val);
|
||||
|
||||
ret = adf4382_set_phase_adjust(adf4382, val);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct iio_attribute adf4382_iio_attrs[] = {
|
||||
{
|
||||
.name = "reference_frequency",
|
||||
.shared = IIO_SHARED_BY_ALL,
|
||||
.priv = ADF4382_IIO_DEV_ATTR_REF_FREQ,
|
||||
.show = adf4382_iio_read_dev_attr,
|
||||
.store = adf4382_iio_write_dev_attr,
|
||||
},
|
||||
{
|
||||
.name = "charge_pump_current",
|
||||
.shared = IIO_SHARED_BY_ALL,
|
||||
.priv = ADF4382_IIO_DEV_ATTR_CHARGE_PUMP_CURRENT,
|
||||
.show = adf4382_iio_read_dev_attr,
|
||||
.store = adf4382_iio_write_dev_attr,
|
||||
},
|
||||
{
|
||||
.name = "charge_pump_current_available",
|
||||
.shared = IIO_SHARED_BY_ALL,
|
||||
.priv = ADF4382_IIO_DEV_ATTR_CHARGE_PUMP_AVAILABLE,
|
||||
.show = adf4382_iio_read_dev_attr,
|
||||
},
|
||||
{
|
||||
.name = "bleed_current",
|
||||
.shared = IIO_SHARED_BY_ALL,
|
||||
.priv = ADF4382_IIO_DEV_ATTR_BLEED_CURRENT,
|
||||
.show = adf4382_iio_read_dev_attr,
|
||||
.store = adf4382_iio_write_dev_attr,
|
||||
},
|
||||
{
|
||||
.name = "reference_doubler_en",
|
||||
.shared = IIO_SHARED_BY_ALL,
|
||||
.priv = ADF4382_IIO_DEV_ATTR_REF_DOUBLER_EN,
|
||||
.show = adf4382_iio_read_dev_attr,
|
||||
.store = adf4382_iio_write_dev_attr,
|
||||
},
|
||||
{
|
||||
.name = "reference_divider",
|
||||
.shared = IIO_SHARED_BY_ALL,
|
||||
.priv = ADF4382_IIO_DEV_ATTR_REF_DIVIDER,
|
||||
.show = adf4382_iio_read_dev_attr,
|
||||
.store = adf4382_iio_write_dev_attr,
|
||||
},
|
||||
{
|
||||
.name = "sw_sync_en",
|
||||
.shared = IIO_SHARED_BY_ALL,
|
||||
.priv = ADF4382_IIO_DEV_ATTR_SW_SYNC,
|
||||
.show = adf4382_iio_read_dev_attr,
|
||||
.store = adf4382_iio_write_dev_attr,
|
||||
},
|
||||
{
|
||||
.name = "ezsync_setup",
|
||||
.shared = IIO_SHARED_BY_ALL,
|
||||
.priv = ADF4382_IIO_DEV_ATTR_EZ_SYNC,
|
||||
.show = adf4382_iio_read_dev_attr,
|
||||
.store = adf4382_iio_write_dev_attr,
|
||||
},
|
||||
{
|
||||
.name = "timed_sync_setup",
|
||||
.shared = IIO_SHARED_BY_ALL,
|
||||
.priv = ADF4382_IIO_DEV_ATTR_TIMED_SYNC,
|
||||
.show = adf4382_iio_read_dev_attr,
|
||||
.store = adf4382_iio_write_dev_attr,
|
||||
},
|
||||
{
|
||||
.name = "fastcal_en",
|
||||
.shared = IIO_SHARED_BY_ALL,
|
||||
.priv = ADF4382_IIO_DEV_ATTR_FASTCAL_EN,
|
||||
.show = adf4382_iio_read_dev_attr,
|
||||
.store = adf4382_iio_write_dev_attr,
|
||||
},
|
||||
{
|
||||
.name = "fastcal_lut_en",
|
||||
.shared = IIO_SHARED_BY_ALL,
|
||||
.priv = ADF4382_IIO_DEV_ATTR_FASTCAL_LUT_EN,
|
||||
.show = adf4382_iio_read_dev_attr,
|
||||
.store = adf4382_iio_write_dev_attr,
|
||||
},
|
||||
{
|
||||
.name = "change_frequency",
|
||||
.shared = IIO_SHARED_BY_ALL,
|
||||
.priv = ADF4382_IIO_DEV_ATTR_FASTCAL_CHANGE_FREQ,
|
||||
.show = adf4382_iio_read_dev_attr,
|
||||
.store = adf4382_iio_write_dev_attr,
|
||||
},
|
||||
{
|
||||
.name = "start_calibration",
|
||||
.shared = IIO_SHARED_BY_ALL,
|
||||
.priv = ADF4382_IIO_DEV_ATTR_FASTCAL_START_CALIBRATION,
|
||||
.show = adf4382_iio_read_dev_attr,
|
||||
.store = adf4382_iio_write_dev_attr,
|
||||
},
|
||||
END_ATTRIBUTES_ARRAY
|
||||
};
|
||||
|
||||
static struct iio_attribute adf4382_iio_ch_attrs[] = {
|
||||
{
|
||||
.name = "en",
|
||||
.shared = IIO_SEPARATE,
|
||||
.priv = ADF4382_IIO_CH_ATTR_EN,
|
||||
.show = adf4382_iio_read_chan_attr,
|
||||
.store = adf4382_iio_write_chan_attr,
|
||||
},
|
||||
{
|
||||
.name = "frequency",
|
||||
.shared = IIO_SHARED_BY_TYPE,
|
||||
.priv = ADF4382_IIO_CH_ATTR_FREQ,
|
||||
.show = adf4382_iio_read_chan_attr,
|
||||
.store = adf4382_iio_write_chan_attr,
|
||||
},
|
||||
{
|
||||
.name = "output_power",
|
||||
.shared = IIO_SEPARATE,
|
||||
.priv = ADF4382_IIO_CH_ATTR_OPWR,
|
||||
.show = adf4382_iio_read_chan_attr,
|
||||
.store = adf4382_iio_write_chan_attr,
|
||||
},
|
||||
{
|
||||
.name = "phase",
|
||||
.shared = IIO_SHARED_BY_TYPE,
|
||||
.priv = ADF4382_IIO_CH_ATTR_PHASE_ADJ,
|
||||
.show = adf4382_iio_read_chan_attr,
|
||||
.store = adf4382_iio_write_chan_attr,
|
||||
},
|
||||
END_ATTRIBUTES_ARRAY
|
||||
};
|
||||
|
||||
static struct iio_channel adf4382_channels[] = {
|
||||
{
|
||||
.ch_type = IIO_ALTVOLTAGE,
|
||||
.channel = 0,
|
||||
.ch_out = true,
|
||||
.indexed = true,
|
||||
.attributes = adf4382_iio_ch_attrs,
|
||||
.scan_type = NULL,
|
||||
},
|
||||
{
|
||||
.ch_type = IIO_ALTVOLTAGE,
|
||||
.channel = 1,
|
||||
.ch_out = true,
|
||||
.indexed = true,
|
||||
.attributes = adf4382_iio_ch_attrs,
|
||||
.scan_type = NULL,
|
||||
},
|
||||
};
|
||||
|
||||
static struct iio_device adf4382_iio_dev = {
|
||||
.num_ch = NO_OS_ARRAY_SIZE(adf4382_channels),
|
||||
.channels = adf4382_channels,
|
||||
.attributes = adf4382_iio_attrs,
|
||||
.debug_reg_read = (int32_t (*)())adf4382_iio_read_reg,
|
||||
.debug_reg_write = (int32_t (*)())adf4382_iio_write_reg
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initializes the ADF4382 IIO driver
|
||||
* @param iio_dev - The iio device structure.
|
||||
* @param init_param - The structure that contains the device initial parameters.
|
||||
* @return ret - Result of the initialization procedure.
|
||||
*/
|
||||
int adf4382_iio_init(struct adf4382_iio_dev **iio_dev,
|
||||
struct adf4382_iio_dev_init_param *init_param)
|
||||
{
|
||||
struct adf4382_iio_dev *dev;
|
||||
int ret;
|
||||
|
||||
dev = (struct adf4382_iio_dev *)no_os_calloc(1, sizeof(*dev));
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->iio_dev = &adf4382_iio_dev;
|
||||
|
||||
ret = adf4382_init(&dev->adf4382_dev, init_param->adf4382_dev_init);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
*iio_dev = dev;
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
no_os_free(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by adf4382_iio_init().
|
||||
* @param dev - The IIO device structure.
|
||||
* @return ret - Result of the remove procedure.
|
||||
*/
|
||||
int adf4382_iio_remove(struct adf4382_iio_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = adf4382_remove(dev->adf4382_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
no_os_free(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/***************************************************************************//**
|
||||
* @file iio_adf4382.h
|
||||
* @brief Implementation of IIO ADF4382 Driver.
|
||||
* @authors Ciprian Hegbeli (ciprian.hegbeli@analog.com)
|
||||
* Jude Osemene (jude.osemene@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2024(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef IIO_ADF4382_H
|
||||
#define IIO_ADF4382_H
|
||||
|
||||
#include "iio.h"
|
||||
|
||||
struct adf4382_iio_dev {
|
||||
struct adf4382_dev *adf4382_dev;
|
||||
struct iio_device *iio_dev;
|
||||
};
|
||||
|
||||
struct adf4382_iio_dev_init_param {
|
||||
struct adf4382_init_param *adf4382_dev_init;
|
||||
};
|
||||
|
||||
enum adf4382_iio_ch_attr_id {
|
||||
ADF4382_IIO_CH_ATTR_EN,
|
||||
ADF4382_IIO_CH_ATTR_FREQ,
|
||||
ADF4382_IIO_CH_ATTR_OPWR,
|
||||
ADF4382_IIO_CH_ATTR_PHASE_ADJ,
|
||||
};
|
||||
|
||||
enum adf4382_iio_dev_attr_id {
|
||||
ADF4382_IIO_DEV_ATTR_REF_FREQ,
|
||||
ADF4382_IIO_DEV_ATTR_BLEED_CURRENT,
|
||||
ADF4382_IIO_DEV_ATTR_CHARGE_PUMP_CURRENT,
|
||||
ADF4382_IIO_DEV_ATTR_CHARGE_PUMP_AVAILABLE,
|
||||
ADF4382_IIO_DEV_ATTR_REF_DIVIDER,
|
||||
ADF4382_IIO_DEV_ATTR_REF_DOUBLER_EN,
|
||||
ADF4382_IIO_DEV_ATTR_SW_SYNC,
|
||||
ADF4382_IIO_DEV_ATTR_EZ_SYNC,
|
||||
ADF4382_IIO_DEV_ATTR_TIMED_SYNC,
|
||||
ADF4382_IIO_DEV_ATTR_FASTCAL_EN,
|
||||
ADF4382_IIO_DEV_ATTR_FASTCAL_LUT_EN,
|
||||
ADF4382_IIO_DEV_ATTR_FASTCAL_CHANGE_FREQ,
|
||||
ADF4382_IIO_DEV_ATTR_FASTCAL_START_CALIBRATION,
|
||||
};
|
||||
|
||||
int adf4382_iio_init(struct adf4382_iio_dev **iio_dev,
|
||||
struct adf4382_iio_dev_init_param *init_param);
|
||||
|
||||
int adf4382_iio_remove(struct adf4382_iio_dev *desc);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,475 @@
|
||||
/***************************************************************************//**
|
||||
* @file iio_app.c
|
||||
* @brief C file of iio_app
|
||||
* @author Mihail Chindris (mihail.chindris@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifdef IIO_SUPPORT
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "iio_app.h"
|
||||
#include "parameters.h"
|
||||
#include "no_os_alloc.h"
|
||||
|
||||
#if defined(ADUCM_PLATFORM)
|
||||
#include "aducm3029_uart.h"
|
||||
#include "aducm3029_irq.h"
|
||||
#endif
|
||||
#if defined(XILINX_PLATFORM)
|
||||
#include "xilinx_uart.h"
|
||||
#include "xilinx_irq.h"
|
||||
#endif
|
||||
#if defined(STM32_PLATFORM)
|
||||
#include <errno.h>
|
||||
#include "stm32_uart.h"
|
||||
#include "stm32_irq.h"
|
||||
#endif
|
||||
#if defined(MAXIM_PLATFORM)
|
||||
#include "maxim_irq.h"
|
||||
#include "maxim_uart.h"
|
||||
#endif
|
||||
|
||||
#ifdef NO_OS_NETWORKING
|
||||
/* Fix: Use static buffers instead of calloc for new connections */
|
||||
#warning "iio may not work with WIFI on aducm3029."
|
||||
#ifdef ADUCM_PLATFORM
|
||||
#include "wifi.h"
|
||||
#endif
|
||||
#include "tcp_socket.h"
|
||||
#endif
|
||||
|
||||
#ifdef LINUX_PLATFORM
|
||||
#include "linux_socket.h"
|
||||
#include "tcp_socket.h"
|
||||
#endif
|
||||
|
||||
#ifdef NO_OS_LWIP_NETWORKING
|
||||
#include "lwip_socket.h"
|
||||
#endif
|
||||
|
||||
// The default baudrate iio_app will use to print messages to console.
|
||||
#define UART_BAUDRATE_DEFAULT 115200
|
||||
#define UART_STOPBITS_DEFAULT NO_OS_UART_STOP_1_BIT
|
||||
|
||||
static inline uint32_t _calc_uart_xfer_time(uint32_t len, uint32_t baudrate)
|
||||
{
|
||||
uint32_t ms = 1000ul * len * 8 / UART_BAUDRATE_DEFAULT;
|
||||
ms += ms / 10; // overhead
|
||||
return ms;
|
||||
}
|
||||
|
||||
#if !defined(LINUX_PLATFORM) && !defined(NO_OS_NETWORKING) && !defined(NO_OS_USB_UART)
|
||||
static int32_t iio_print_uart_info_message(struct no_os_uart_desc **uart_desc,
|
||||
struct no_os_uart_init_param *user_uart_params,
|
||||
char *message, int32_t msglen)
|
||||
{
|
||||
int32_t status;
|
||||
uint32_t delay_ms;
|
||||
|
||||
status = no_os_uart_write(*uart_desc, (uint8_t *)message, msglen);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
delay_ms = _calc_uart_xfer_time(msglen, UART_BAUDRATE_DEFAULT);
|
||||
no_os_mdelay(delay_ms);
|
||||
|
||||
/** Reinitialize UART with parameters required by the IIO application */
|
||||
no_os_uart_remove(*uart_desc);
|
||||
return no_os_uart_init(uart_desc, user_uart_params);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32_t print_uart_hello_message(struct no_os_uart_desc **uart_desc,
|
||||
struct no_os_uart_init_param *user_uart_params)
|
||||
{
|
||||
#if defined(LINUX_PLATFORM) || defined(NO_OS_NETWORKING) || defined(NO_OS_LWIP_NETWORKING) || defined(NO_OS_USB_UART)
|
||||
return 0;
|
||||
#else
|
||||
const char *uart_data_size[] = { "5", "6", "7", "8", "9" };
|
||||
const char *uart_parity[] = { "none", "mark", "space", "odd", "even" };
|
||||
const char *uart_stop[] = { "1", "2" };
|
||||
char message[512];
|
||||
uint32_t msglen = sprintf(message,
|
||||
"Running IIOD server...\n"
|
||||
"If successful, you may connect an IIO client application by:\n"
|
||||
"1. Disconnecting the serial terminal you use to view this message.\n"
|
||||
"2. Connecting the IIO client application using the serial backend configured as shown:\n"
|
||||
"\tBaudrate: %lu\n"
|
||||
"\tData size: %s bits\n"
|
||||
"\tParity: %s\n"
|
||||
"\tStop bits: %s\n"
|
||||
"\tFlow control: none\n",
|
||||
user_uart_params->baud_rate,
|
||||
uart_data_size[user_uart_params->size],
|
||||
uart_parity[user_uart_params->parity],
|
||||
uart_stop[user_uart_params->stop]);
|
||||
|
||||
return iio_print_uart_info_message(uart_desc, user_uart_params,
|
||||
message, msglen);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int32_t print_uart_error_message(struct no_os_uart_desc **uart_desc,
|
||||
struct no_os_uart_init_param *user_uart_params,
|
||||
int32_t status)
|
||||
{
|
||||
char message[512];
|
||||
uint32_t msglen = sprintf(message,
|
||||
"IIOD server failed with code %d.\n",
|
||||
(int)status);
|
||||
#if defined(LINUX_PLATFORM) || defined(NO_OS_NETWORKING) || defined(NO_OS_LWIP_NETWORKING) || defined(NO_OS_USB_UART)
|
||||
(void)msglen;
|
||||
printf("%s", message);
|
||||
return 0;
|
||||
#else
|
||||
return iio_print_uart_info_message(uart_desc, user_uart_params,
|
||||
message, msglen);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(NO_OS_LWIP_NETWORKING)
|
||||
static int32_t lwip_network_setup(struct iio_app_desc *app,
|
||||
struct iio_app_init_param param,
|
||||
struct iio_init_param *iio_init_param)
|
||||
{
|
||||
static struct tcp_socket_init_param socket_param;
|
||||
static struct lwip_network_desc lwip_desc;
|
||||
static bool is_initialized = false;
|
||||
int ret;
|
||||
|
||||
if (NO_OS_LWIP_INIT_ONETIME && is_initialized) {
|
||||
socket_param.net = &lwip_desc.no_os_net;
|
||||
} else {
|
||||
ret = no_os_lwip_init(&app->lwip_desc, ¶m.lwip_param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
socket_param.net = &app->lwip_desc->no_os_net;
|
||||
memcpy(&lwip_desc, app->lwip_desc, sizeof(lwip_desc));
|
||||
}
|
||||
|
||||
is_initialized = true;
|
||||
socket_param.max_buff_size = 0;
|
||||
|
||||
iio_init_param->phy_type = USE_NETWORK;
|
||||
iio_init_param->tcp_socket_init_param = &socket_param;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(NO_OS_NETWORKING) || defined(LINUX_PLATFORM)
|
||||
static int32_t network_setup(struct iio_init_param *iio_init_param,
|
||||
struct no_os_uart_desc *uart_desc,
|
||||
void *irq_desc)
|
||||
{
|
||||
static struct tcp_socket_init_param socket_param;
|
||||
|
||||
#ifdef LINUX_PLATFORM
|
||||
socket_param.net = &linux_net;
|
||||
#endif
|
||||
#ifdef ADUCM_PLATFORM
|
||||
int32_t status;
|
||||
static struct wifi_desc *wifi;
|
||||
struct wifi_init_param wifi_param = {
|
||||
.irq_desc = irq_desc,
|
||||
.uart_desc = uart_desc,
|
||||
.uart_irq_conf = uart_desc,
|
||||
.uart_irq_id = UART_IRQ_ID,
|
||||
.sw_reset_en = true
|
||||
};
|
||||
status = wifi_init(&wifi, &wifi_param);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
status = wifi_connect(wifi, WIFI_SSID, WIFI_PWD);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
char buff[100];
|
||||
wifi_get_ip(wifi, buff, 100);
|
||||
printf("iiod ip is: %s\n", buff);
|
||||
|
||||
wifi_get_network_interface(wifi, &socket_param.net);
|
||||
#endif
|
||||
|
||||
socket_param.max_buff_size = 0;
|
||||
iio_init_param->phy_type = USE_NETWORK;
|
||||
iio_init_param->tcp_socket_init_param = &socket_param;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32_t uart_setup(struct no_os_uart_desc **uart_desc,
|
||||
struct no_os_uart_init_param *uart_init_par)
|
||||
{
|
||||
#if defined(LINUX_PLATFORM) || defined(NO_OS_LWIP_NETWORKING)
|
||||
*uart_desc = NULL;
|
||||
return 0;
|
||||
#endif
|
||||
struct no_os_uart_init_param luart_par = {
|
||||
.device_id = uart_init_par->device_id,
|
||||
/* TODO: remove this ifdef when asynchrounous rx is implemented on every platform. */
|
||||
#if defined(STM32_PLATFORM) || defined(MAXIM_PLATFORM) || defined(ADUCM_PLATFORM) || defined(PICO_PLATFORM)
|
||||
.irq_id = uart_init_par->irq_id,
|
||||
.asynchronous_rx = true,
|
||||
#endif
|
||||
.baud_rate = UART_BAUDRATE_DEFAULT,
|
||||
.size = NO_OS_UART_CS_8,
|
||||
.parity = NO_OS_UART_PAR_NO,
|
||||
.stop = NO_OS_UART_STOP_1_BIT,
|
||||
.platform_ops = uart_init_par->platform_ops,
|
||||
#ifndef ADUCM_PLATFORM
|
||||
.extra = uart_init_par->extra
|
||||
#endif
|
||||
};
|
||||
|
||||
return no_os_uart_init(uart_desc, &luart_par);
|
||||
}
|
||||
|
||||
#if defined(ADUCM_PLATFORM) || (defined(STM32_PLATFORM)) || defined(MAXIM_PLATFORM)
|
||||
static int32_t irq_setup(struct no_os_irq_ctrl_desc **irq_desc)
|
||||
{
|
||||
int32_t status;
|
||||
#if defined(ADUCM_PLATFORM)
|
||||
void *platform_irq_init_par = NULL;
|
||||
const struct no_os_irq_platform_ops *platform_irq_ops = &aducm_irq_ops;
|
||||
#elif defined(STM32_PLATFORM)
|
||||
void *platform_irq_init_par = NULL;
|
||||
const struct no_os_irq_platform_ops *platform_irq_ops = &stm32_irq_ops;
|
||||
#elif defined(MAXIM_PLATFORM)
|
||||
void *platform_irq_init_par = NULL;
|
||||
const struct no_os_irq_platform_ops *platform_irq_ops = &max_irq_ops;
|
||||
#endif
|
||||
|
||||
struct no_os_irq_init_param irq_init_param = {
|
||||
.irq_ctrl_id = INTC_DEVICE_ID,
|
||||
.platform_ops = platform_irq_ops,
|
||||
.extra = platform_irq_init_par
|
||||
};
|
||||
|
||||
status = no_os_irq_ctrl_init(irq_desc, &irq_init_param);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
return no_os_irq_global_enable(*irq_desc);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Register devices for an iio application
|
||||
*
|
||||
* Configuration for communication is done in parameters.h
|
||||
* @param app - the iio application descriptor
|
||||
* @param app_init_param - the iio application initialization parameters
|
||||
* @return 0 on success, negative value otherwise
|
||||
*/
|
||||
int iio_app_init(struct iio_app_desc **app,
|
||||
struct iio_app_init_param app_init_param)
|
||||
{
|
||||
struct iio_device_init *iio_init_devs = NULL;
|
||||
struct iio_init_param iio_init_param;
|
||||
struct no_os_uart_desc *uart_desc;
|
||||
struct iio_app_desc *application;
|
||||
struct iio_data_buffer *buff;
|
||||
unsigned int i;
|
||||
int status;
|
||||
void *irq_desc = app_init_param.irq_desc;
|
||||
|
||||
application = (struct iio_app_desc *)no_os_calloc(1, sizeof(*application));
|
||||
if (!application)
|
||||
return -ENOMEM;
|
||||
|
||||
application->post_step_callback = app_init_param.post_step_callback;
|
||||
application->arg = app_init_param.arg;
|
||||
|
||||
#if defined(ADUCM_PLATFORM) || defined(STM32_PLATFORM)
|
||||
/* Only one irq controller can exist and be initialized in
|
||||
* any of the iio_devices. */
|
||||
for (i = 0; i < app_init_param.nb_devices; i++) {
|
||||
if (app_init_param.devices[i].dev_descriptor->irq_desc) {
|
||||
irq_desc = (struct no_os_irq_ctrl_desc *)
|
||||
app_init_param.devices[i].dev_descriptor->irq_desc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!irq_desc) {
|
||||
status = irq_setup((struct no_os_irq_ctrl_desc **)&irq_desc);
|
||||
if (status < 0)
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
status = uart_setup(&uart_desc, &app_init_param.uart_init_params);
|
||||
if (status < 0)
|
||||
goto error_uart;
|
||||
|
||||
status = print_uart_hello_message(&uart_desc,
|
||||
&app_init_param.uart_init_params);
|
||||
if (status < 0)
|
||||
goto error;
|
||||
|
||||
application->uart_desc = uart_desc;
|
||||
#if defined(NO_OS_LWIP_NETWORKING)
|
||||
status = lwip_network_setup(application, app_init_param, &iio_init_param);
|
||||
if (status)
|
||||
goto error;
|
||||
#elif defined(NO_OS_NETWORKING) || defined(LINUX_PLATFORM)
|
||||
status = network_setup(&iio_init_param, uart_desc, application->irq_desc);
|
||||
if (status < 0)
|
||||
goto error;
|
||||
#else
|
||||
iio_init_param.phy_type = USE_UART;
|
||||
iio_init_param.uart_desc = uart_desc;
|
||||
#endif
|
||||
|
||||
iio_init_devs = no_os_calloc(app_init_param.nb_devices, sizeof(*iio_init_devs));
|
||||
if (!iio_init_devs) {
|
||||
status = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; i < app_init_param.nb_devices; ++i) {
|
||||
/*
|
||||
* iio_app_device is from iio_app.h and we don't want to include
|
||||
* this in iio.h.
|
||||
* At the moment iio_device_init has the same parameters but
|
||||
* it will change.
|
||||
* When changes are done in iio. iio_app_device may be removed
|
||||
*iio_init_param and use iio_device_init instead.
|
||||
* This way faster changes can be done without changing all
|
||||
* project for each change.
|
||||
*/
|
||||
iio_init_devs[i].name = app_init_param.devices[i].name;
|
||||
iio_init_devs[i].dev = app_init_param.devices[i].dev;
|
||||
iio_init_devs[i].dev_descriptor = app_init_param.devices[i].dev_descriptor;
|
||||
iio_init_devs[i].trigger_id = app_init_param.devices[i].default_trigger_id;
|
||||
buff = app_init_param.devices[i].read_buff ?
|
||||
app_init_param.devices[i].read_buff :
|
||||
app_init_param.devices[i].write_buff;
|
||||
if (buff) {
|
||||
iio_init_devs[i].raw_buf = buff->buff;
|
||||
iio_init_devs[i].raw_buf_len = buff->size;
|
||||
} else {
|
||||
iio_init_devs[i].raw_buf = NULL;
|
||||
iio_init_devs[i].raw_buf_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
iio_init_param.devs = iio_init_devs;
|
||||
iio_init_param.nb_devs = app_init_param.nb_devices;
|
||||
iio_init_param.trigs = app_init_param.trigs;
|
||||
iio_init_param.nb_trigs = app_init_param.nb_trigs;
|
||||
iio_init_param.ctx_attrs = app_init_param.ctx_attrs;
|
||||
iio_init_param.nb_ctx_attr = app_init_param.nb_ctx_attr;
|
||||
|
||||
status = iio_init(&application->iio_desc, &iio_init_param);
|
||||
if (status < 0)
|
||||
goto error;
|
||||
|
||||
no_os_free(iio_init_devs);
|
||||
|
||||
*app = application;
|
||||
|
||||
return 0;
|
||||
error_uart:
|
||||
/** We might have to reinit UART, settings might have changed for IIO */
|
||||
uart_setup(&uart_desc, &app_init_param.uart_init_params);
|
||||
error:
|
||||
no_os_free(iio_init_devs);
|
||||
|
||||
no_os_free(application);
|
||||
|
||||
print_uart_error_message(&uart_desc, &app_init_param.uart_init_params, status);
|
||||
no_os_uart_remove(uart_desc);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start an IIO application
|
||||
*
|
||||
* Configuration for communication is done through iio_app_init_param
|
||||
* @param app - the iio application parameters
|
||||
* @return 0 on success, negative value otherwise
|
||||
*/
|
||||
int iio_app_run(struct iio_app_desc *app)
|
||||
{
|
||||
int status;
|
||||
|
||||
do {
|
||||
status = iio_step(app->iio_desc);
|
||||
if (status && status != -EAGAIN && status != -ENOTCONN
|
||||
&& status != -NO_OS_EOVERRUN)
|
||||
return status;
|
||||
if (app->post_step_callback) {
|
||||
status = app->post_step_callback(app->arg);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove resources allocated by the IIO application
|
||||
*
|
||||
* Configuration for communication is done through iio_app_init_param
|
||||
* @param app - the iio application parameters
|
||||
* @return 0 on success, negative value otherwise
|
||||
*/
|
||||
int iio_app_remove(struct iio_app_desc *app)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if defined(ADUCM_PLATFORM) || (defined(XILINX_PLATFORM) && !defined(PLATFORM_MB)) || defined(STM32_PLATFORM)
|
||||
ret = no_os_irq_ctrl_remove(app->irq_desc);
|
||||
if (ret)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
if (app->uart_desc) {
|
||||
ret = no_os_uart_remove(app->uart_desc);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = iio_remove(app->iio_desc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
no_os_free(app);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,138 @@
|
||||
/***************************************************************************//**
|
||||
* @file iio_app.h
|
||||
* @brief Header file of iio_app
|
||||
* @author Mihail Chindris (mihail.chindris@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2013(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef IIO_APP
|
||||
#define IIO_APP
|
||||
|
||||
#include "iio.h"
|
||||
#include "no_os_irq.h"
|
||||
#include "no_os_uart.h"
|
||||
#include "no_os_error.h"
|
||||
#include "no_os_delay.h"
|
||||
|
||||
#if defined(NO_OS_LWIP_NETWORKING)
|
||||
#include "lwip_socket.h"
|
||||
#endif
|
||||
|
||||
#define IIO_APP_DEVICE(_name, _dev, _dev_descriptor, _read_buff, _write_buff, _default_trigger_id) {\
|
||||
.name = _name,\
|
||||
.dev = _dev,\
|
||||
.dev_descriptor = _dev_descriptor,\
|
||||
.read_buff = _read_buff,\
|
||||
.write_buff = _write_buff,\
|
||||
.default_trigger_id = _default_trigger_id\
|
||||
}
|
||||
|
||||
#define IIO_APP_TRIGGER(_name, _trig, _trig_descriptor) {\
|
||||
.name = _name,\
|
||||
.trig = _trig,\
|
||||
.descriptor = _trig_descriptor,\
|
||||
}
|
||||
|
||||
struct iio_data_buffer {
|
||||
uint32_t size;
|
||||
void *buff;
|
||||
};
|
||||
|
||||
struct iio_app_device {
|
||||
char *name;
|
||||
void *dev;
|
||||
struct iio_device *dev_descriptor;
|
||||
struct iio_data_buffer *read_buff;
|
||||
struct iio_data_buffer *write_buff;
|
||||
char *default_trigger_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct iio_app_desc
|
||||
* @brief IIO application descriptor.
|
||||
*/
|
||||
struct iio_app_desc {
|
||||
/** UART descriptor to be used */
|
||||
struct no_os_uart_desc *uart_desc;
|
||||
/** IRQ descriptor to be used */
|
||||
void *irq_desc;
|
||||
/** IIO descriptor to be returned */
|
||||
struct iio_desc *iio_desc;
|
||||
/** Function to be called each step */
|
||||
int (*post_step_callback)(void *arg);
|
||||
/** Function parameteres */
|
||||
void *arg;
|
||||
|
||||
#ifdef NO_OS_LWIP_NETWORKING
|
||||
struct lwip_network_desc *lwip_desc;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct iio_app_init_param
|
||||
* @brief IIO application descriptor initialization parameters.
|
||||
*/
|
||||
struct iio_app_init_param {
|
||||
/** Array of context attribute name/value pairs */
|
||||
struct iio_ctx_attr *ctx_attrs;
|
||||
/** Number of context attributes in the array above */
|
||||
uint32_t nb_ctx_attr;
|
||||
/** Array of IIO devices */
|
||||
struct iio_app_device *devices;
|
||||
/** Number of devices */
|
||||
uint32_t nb_devices;
|
||||
/** IIO triggers to be used */
|
||||
struct iio_trigger_init *trigs;
|
||||
/** Number of triggers to be used */
|
||||
int32_t nb_trigs;
|
||||
/** UART init params */
|
||||
struct no_os_uart_init_param uart_init_params;
|
||||
/** IRQ descriptor to be used */
|
||||
void *irq_desc;
|
||||
/** Function to be called each step */
|
||||
int (*post_step_callback)(void *arg);
|
||||
/** Function parameteres */
|
||||
void *arg;
|
||||
|
||||
#ifdef NO_OS_LWIP_NETWORKING
|
||||
struct lwip_network_param lwip_param;
|
||||
#endif
|
||||
};
|
||||
|
||||
/** Register devices for an IIO application */
|
||||
int iio_app_init(struct iio_app_desc **app,
|
||||
struct iio_app_init_param app_init_param);
|
||||
|
||||
/** Start an IIO application */
|
||||
int iio_app_run(struct iio_app_desc *app);
|
||||
|
||||
/** Remove resources allocated by the IIO application */
|
||||
int iio_app_remove(struct iio_app_desc *app);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,227 @@
|
||||
/***************************************************************************//**
|
||||
* @file iio_trigger.c
|
||||
* @brief Implementation of generic iio trigger.
|
||||
* @author RBolboac (ramona.bolboaca@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2022(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "no_os_error.h"
|
||||
#include "no_os_alloc.h"
|
||||
#include "iio.h"
|
||||
#include "iio_trigger.h"
|
||||
|
||||
#ifndef LINUX_PLATFORM
|
||||
/**
|
||||
* @brief Initialize hardware trigger.
|
||||
*
|
||||
* @param iio_trig - The iio trigger structure.
|
||||
* @param init_param - The structure that contains the trigger initial params.
|
||||
*
|
||||
* @return ret - Result of the initialization procedure.
|
||||
*/
|
||||
int iio_hw_trig_init(struct iio_hw_trig **iio_trig,
|
||||
struct iio_hw_trig_init_param *init_param)
|
||||
{
|
||||
struct iio_hw_trig *trig_desc;
|
||||
int ret;
|
||||
|
||||
if (!init_param->name)
|
||||
return -EINVAL;
|
||||
|
||||
trig_desc = (struct iio_hw_trig*)no_os_calloc(1, sizeof(*trig_desc));
|
||||
if (!trig_desc)
|
||||
return -ENOMEM;
|
||||
|
||||
trig_desc->iio_desc = init_param->iio_desc;
|
||||
strncpy(trig_desc->name, init_param->name, TRIG_MAX_NAME_SIZE);
|
||||
trig_desc->irq_ctrl = init_param->irq_ctrl;
|
||||
trig_desc->irq_id = init_param->irq_id;
|
||||
trig_desc->irq_trig_lvl = init_param->irq_trig_lvl;
|
||||
|
||||
struct no_os_callback_desc irq_cb = {
|
||||
.callback = iio_hw_trig_handler,
|
||||
.ctx = trig_desc,
|
||||
.event = init_param->cb_info.event,
|
||||
.handle = init_param->cb_info.handle,
|
||||
.peripheral = init_param->cb_info.peripheral
|
||||
};
|
||||
|
||||
ret = no_os_irq_register_callback(trig_desc->irq_ctrl,
|
||||
trig_desc->irq_id, &irq_cb);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if (init_param->cb_info.event == NO_OS_EVT_GPIO) {
|
||||
ret = no_os_irq_trigger_level_set(trig_desc->irq_ctrl,
|
||||
trig_desc->irq_id, trig_desc->irq_trig_lvl);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
*iio_trig = trig_desc;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
no_os_free(trig_desc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable system interrupt which is linked to the given trigger.
|
||||
*
|
||||
* @param trig - Trigger structure.
|
||||
*
|
||||
* @return ret - Result of the enable procedure.
|
||||
*/
|
||||
int iio_trig_enable(void *trig)
|
||||
{
|
||||
if (!trig)
|
||||
return -EINVAL;
|
||||
|
||||
struct iio_hw_trig *desc = trig;
|
||||
|
||||
return no_os_irq_enable(desc->irq_ctrl, desc->irq_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable system interrupt which is linked to the given trigger.
|
||||
*
|
||||
* @param trig - Trigger structure.
|
||||
*
|
||||
* @return ret - Result of the disable procedure.
|
||||
*/
|
||||
int iio_trig_disable(void *trig)
|
||||
{
|
||||
if (!trig)
|
||||
return -EINVAL;
|
||||
|
||||
struct iio_hw_trig *desc = trig;
|
||||
|
||||
return no_os_irq_disable(desc->irq_ctrl, desc->irq_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Trigger interrupt handler. This function will be called when a system
|
||||
* interrupt is asserted for the configured trigger.
|
||||
*
|
||||
* @param trig - Trigger structure which is linked to this handler.
|
||||
*/
|
||||
void iio_hw_trig_handler(void *trig)
|
||||
{
|
||||
if (!trig)
|
||||
return;
|
||||
|
||||
struct iio_hw_trig *desc = trig;
|
||||
|
||||
iio_process_trigger_type(desc->iio_desc, desc->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by iio_hw_trig_init().
|
||||
*
|
||||
* @param trig - The trigger structure.
|
||||
*
|
||||
* @return ret - Result of the remove procedure.
|
||||
*/
|
||||
int iio_hw_trig_remove(struct iio_hw_trig *trig)
|
||||
{
|
||||
if (trig)
|
||||
no_os_free(trig);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize software trigger.
|
||||
*
|
||||
* @param iio_trig - The iio trigger structure.
|
||||
* @param init_param - The structure that contains the sw trigger initial params.
|
||||
*
|
||||
* @return ret - Result of the initialization procedure.
|
||||
*/
|
||||
int iio_sw_trig_init(struct iio_sw_trig **iio_trig,
|
||||
struct iio_sw_trig_init_param *init_param)
|
||||
{
|
||||
struct iio_sw_trig *trig_desc;
|
||||
|
||||
if (!init_param->iio_desc || !init_param->name)
|
||||
return -EINVAL;
|
||||
|
||||
trig_desc = (struct iio_sw_trig*)no_os_calloc(1, sizeof(*trig_desc));
|
||||
if (!trig_desc)
|
||||
return -ENOMEM;
|
||||
|
||||
trig_desc->iio_desc = init_param->iio_desc;
|
||||
strncpy(trig_desc->name, init_param->name, TRIG_MAX_NAME_SIZE);
|
||||
|
||||
*iio_trig = trig_desc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles the write request for trigger_now attribute.
|
||||
*
|
||||
* @param trig - The iio trigger structure.
|
||||
* @param buf - Command buffer to be filled with the data to be written.
|
||||
* @param len - Length of the received command buffer in bytes.
|
||||
* @param channel - Command channel info (is NULL).
|
||||
* @param priv - Command attribute id.
|
||||
*
|
||||
* @return ret - Result of the sw trigger handler procedure.
|
||||
*/
|
||||
int iio_sw_trig_handler(void *trig, char *buf, uint32_t len,
|
||||
const struct iio_ch_info *channel,
|
||||
intptr_t priv)
|
||||
{
|
||||
if (!trig)
|
||||
return -EINVAL;
|
||||
|
||||
struct iio_sw_trig *desc = trig;
|
||||
|
||||
return iio_process_trigger_type(desc->iio_desc, desc->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by iio_sw_trig_init().
|
||||
*
|
||||
* @param trig - The trigger structure.
|
||||
*
|
||||
* @return ret - Result of the remove procedure.
|
||||
*/
|
||||
int iio_sw_trig_remove(struct iio_sw_trig *trig)
|
||||
{
|
||||
if (trig)
|
||||
no_os_free(trig);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/***************************************************************************//**
|
||||
* @file iio_trigger.h
|
||||
* @brief Header file for iio_trigger.
|
||||
* @author RBolboac(ramona.bolboaca@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2022(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef IIO_TRIGGER_H_
|
||||
#define IIO_TRIGGER_H_
|
||||
|
||||
#include "iio.h"
|
||||
#include "iio_types.h"
|
||||
#include "no_os_irq.h"
|
||||
|
||||
#define TRIG_MAX_NAME_SIZE 20
|
||||
|
||||
/**
|
||||
* @struct iio_hw_trig
|
||||
* @brief IIO hardware trigger structure
|
||||
*/
|
||||
struct iio_hw_trig {
|
||||
/** IIO descriptor */
|
||||
struct iio_desc *iio_desc;
|
||||
/** Interrupt descriptor to be linked with the trigger */
|
||||
struct no_os_irq_ctrl_desc *irq_ctrl;
|
||||
/** Interrupt id to be linked with the trigger */
|
||||
uint32_t irq_id;
|
||||
/** Interrupt trigger level */
|
||||
enum no_os_irq_trig_level irq_trig_lvl;
|
||||
/** Device trigger name */
|
||||
char name[TRIG_MAX_NAME_SIZE + 1];
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct iio_hw_trig_cb_info
|
||||
* @brief Hardware trigger callback extra information structure
|
||||
*/
|
||||
struct iio_hw_trig_cb_info {
|
||||
/** Platform specific event that triggers the calling of the callback. */
|
||||
enum no_os_irq_event event;
|
||||
/** Interrupt source peripheral specifier. */
|
||||
enum no_os_irq_peripheral peripheral;
|
||||
/** This will be used to store HAL specific descriptors */
|
||||
void *handle;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct iio_hw_trig_init_param
|
||||
* @brief IIO hardware trigger initialization structure
|
||||
*/
|
||||
struct iio_hw_trig_init_param {
|
||||
/** IIO descriptor */
|
||||
struct iio_desc *iio_desc;
|
||||
/** Interrupt descriptor to be linked with the trigger */
|
||||
struct no_os_irq_ctrl_desc *irq_ctrl;
|
||||
/** Interrupt id to be linked with the trigger */
|
||||
uint32_t irq_id;
|
||||
/** Interrupt trigger level */
|
||||
enum no_os_irq_trig_level irq_trig_lvl;
|
||||
/** Additional interrupt callback information */
|
||||
struct iio_hw_trig_cb_info cb_info;
|
||||
/** Device trigger name */
|
||||
const char *name;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct iio_sw_trig
|
||||
* @brief IIO software trigger structure
|
||||
*/
|
||||
struct iio_sw_trig {
|
||||
/** IIO descriptor */
|
||||
struct iio_desc *iio_desc;
|
||||
/** Device trigger name */
|
||||
char name[TRIG_MAX_NAME_SIZE + 1];
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct iio_sw_trig_init_param
|
||||
* @brief IIO software trigger initialization structure
|
||||
*/
|
||||
struct iio_sw_trig_init_param {
|
||||
/** IIO descriptor */
|
||||
struct iio_desc *iio_desc;
|
||||
/** Device trigger name */
|
||||
const char *name;
|
||||
};
|
||||
|
||||
#ifndef LINUX_PLATFORM
|
||||
/** API to initialize a hardware trigger */
|
||||
int iio_hw_trig_init(struct iio_hw_trig **iio_trig,
|
||||
struct iio_hw_trig_init_param *init_param);
|
||||
/** API to enable a hardware trigger */
|
||||
int iio_trig_enable(void *trig);
|
||||
/** API to disable a hardware trigger */
|
||||
int iio_trig_disable(void *trig);
|
||||
/** API for hardware trigger handler */
|
||||
void iio_hw_trig_handler(void *trig);
|
||||
/** API to remove a hardware trigger */
|
||||
int iio_hw_trig_remove(struct iio_hw_trig *trig);
|
||||
#endif
|
||||
|
||||
/** API to initialize a software trigger */
|
||||
int iio_sw_trig_init(struct iio_sw_trig **iio_trig,
|
||||
struct iio_sw_trig_init_param *init_param);
|
||||
/** API for software trigger handler */
|
||||
int iio_sw_trig_handler(void *trig, char *buf, uint32_t len,
|
||||
const struct iio_ch_info *channel,
|
||||
intptr_t priv);
|
||||
/** API to remove a software trigger */
|
||||
int iio_trig_remove(struct iio_sw_trig *trig);
|
||||
|
||||
#endif /* IIO_TRIGGER_H_ */
|
||||
@@ -0,0 +1,280 @@
|
||||
/***************************************************************************//**
|
||||
* @file iio_types.h
|
||||
* @brief Header file for iio_types
|
||||
* @author Cristian Pop (cristian.pop@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2013(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef IIO_TYPES_H_
|
||||
#define IIO_TYPES_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "no_os_circular_buffer.h"
|
||||
|
||||
enum iio_val {
|
||||
IIO_VAL_INT = 1,
|
||||
IIO_VAL_INT_PLUS_MICRO,
|
||||
IIO_VAL_INT_PLUS_NANO,
|
||||
IIO_VAL_INT_PLUS_MICRO_DB,
|
||||
IIO_VAL_INT_MULTIPLE,
|
||||
IIO_VAL_FRACTIONAL = 10,
|
||||
IIO_VAL_FRACTIONAL_LOG2,
|
||||
IIO_VAL_CHAR
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct iio_chan_type
|
||||
* @brief IIO channel types
|
||||
*/
|
||||
enum iio_chan_type {
|
||||
IIO_VOLTAGE,
|
||||
IIO_CURRENT,
|
||||
IIO_ALTVOLTAGE,
|
||||
IIO_ANGL_VEL,
|
||||
IIO_TEMP,
|
||||
IIO_CAPACITANCE,
|
||||
IIO_ACCEL,
|
||||
IIO_RESISTANCE,
|
||||
IIO_MAGN,
|
||||
IIO_INCLI,
|
||||
IIO_VELOCITY,
|
||||
IIO_ANGL,
|
||||
IIO_ROT,
|
||||
IIO_COUNT,
|
||||
IIO_DELTA_ANGL,
|
||||
IIO_DELTA_VELOCITY,
|
||||
IIO_WEIGHT,
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct iio_modifier
|
||||
* @brief IIO channel modifier
|
||||
*/
|
||||
enum iio_modifier {
|
||||
IIO_NO_MOD,
|
||||
IIO_MOD_X,
|
||||
IIO_MOD_Y,
|
||||
IIO_MOD_Z,
|
||||
IIO_MOD_TEMP_AMBIENT,
|
||||
IIO_MOD_PITCH,
|
||||
IIO_MOD_YAW,
|
||||
IIO_MOD_ROLL,
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct iio_ch_info
|
||||
* @brief Structure holding channel attributess.
|
||||
*/
|
||||
struct iio_ch_info {
|
||||
/** Channel number. TODO: refactor out the ch_ prefix. */
|
||||
int16_t ch_num;
|
||||
/** Channel direction: input/output. TODO: refactor out the ch_ prefix. */
|
||||
bool ch_out;
|
||||
/** Channel type */
|
||||
enum iio_chan_type type;
|
||||
/** Differential channel indicator */
|
||||
bool differential;
|
||||
/** Driver specific identifier. */
|
||||
uint32_t address;
|
||||
};
|
||||
|
||||
#define END_ATTRIBUTES_ARRAY {.name = NULL}
|
||||
|
||||
enum iio_attribute_shared {
|
||||
IIO_SEPARATE,
|
||||
IIO_SHARED_BY_TYPE,
|
||||
IIO_SHARED_BY_DIR,
|
||||
IIO_SHARED_BY_ALL,
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct iio_attribute
|
||||
* @brief Structure holding pointers to show and store functions.
|
||||
*/
|
||||
struct iio_attribute {
|
||||
/** Attribute name */
|
||||
const char *name;
|
||||
/** Attribute id */
|
||||
intptr_t priv;
|
||||
/** Whether this attribute is shared by all channels of the same type, or direction
|
||||
* or simply by all channels. If left uninitialized, the sharedness defaults to
|
||||
* separate.
|
||||
*/
|
||||
enum iio_attribute_shared shared;
|
||||
/** Show function pointer */
|
||||
int (*show)(void *device, char *buf, uint32_t len,
|
||||
const struct iio_ch_info *channel, intptr_t priv);
|
||||
/** Store function pointer */
|
||||
int (*store)(void *device, char *buf, uint32_t len,
|
||||
const struct iio_ch_info *channel, intptr_t priv);
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct iio_channel
|
||||
* @brief Struct describing the scan type
|
||||
*/
|
||||
struct scan_type {
|
||||
/** 's' or 'u' to specify signed or unsigned */
|
||||
char sign;
|
||||
/** Number of valid bits of data */
|
||||
uint8_t realbits;
|
||||
/** Realbits + padding */
|
||||
uint8_t storagebits;
|
||||
/** Shift right by this before masking out realbits. */
|
||||
uint8_t shift;
|
||||
/** True if big endian, false if little endian */
|
||||
bool is_big_endian;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct iio_channel
|
||||
* @brief Structure holding attributes of a channel.
|
||||
*/
|
||||
struct iio_channel {
|
||||
/** Channel name */
|
||||
const char *name;
|
||||
/** Chanel type */
|
||||
enum iio_chan_type ch_type;
|
||||
/** Channel number when the same channel type */
|
||||
int channel;
|
||||
/** If modified is set, this provides the modifier. E.g. IIO_MOD_X
|
||||
* for angular rate when applied to channel2 will make make the
|
||||
* IIO_ANGL_VEL have anglvel_x which corresponds to the x-axis. */
|
||||
int channel2;
|
||||
/** Driver specific identifier. */
|
||||
unsigned long address;
|
||||
/** Index to give ordering in scans when read from a buffer. */
|
||||
int scan_index;
|
||||
/** */
|
||||
struct scan_type *scan_type;
|
||||
/** Array of attributes. Last one should have its name set to NULL */
|
||||
struct iio_attribute *attributes;
|
||||
/** if true, the channel is an output channel */
|
||||
bool ch_out;
|
||||
/** Set if channel has a modifier. Use channel2 property to
|
||||
* select the modifier to use.*/
|
||||
bool modified;
|
||||
/** Specify if channel has a numerical index. If not set, channel
|
||||
* number will be suppressed. */
|
||||
bool indexed;
|
||||
/* Set if the channel is differential. */
|
||||
bool diferential;
|
||||
};
|
||||
|
||||
enum iio_buffer_direction {
|
||||
IIO_DIRECTION_INPUT,
|
||||
IIO_DIRECTION_OUTPUT
|
||||
};
|
||||
|
||||
struct iio_cyclic_buffer_info {
|
||||
bool is_cyclic;
|
||||
uint32_t buff_index;
|
||||
};
|
||||
|
||||
struct iio_buffer {
|
||||
/* Mask with active channels */
|
||||
uint32_t active_mask;
|
||||
/* Size in bytes */
|
||||
uint32_t size;
|
||||
/* Number of bytes per sample * number of active channels */
|
||||
uint32_t bytes_per_scan;
|
||||
/* Number of requested samples */
|
||||
uint32_t samples;
|
||||
/* Buffer direction */
|
||||
enum iio_buffer_direction dir;
|
||||
/* Buffer where data is stored */
|
||||
struct no_os_circular_buffer *buf;
|
||||
/* Stores cyclic buffer specific information */
|
||||
struct iio_cyclic_buffer_info cyclic_info;
|
||||
};
|
||||
|
||||
struct iio_device_data {
|
||||
void *dev;
|
||||
struct iio_buffer *buffer;
|
||||
};
|
||||
|
||||
struct iio_trigger {
|
||||
/** If true the trigger handler will be called in interrupt context
|
||||
* If false the handler will be called from iio_step */
|
||||
bool is_synchronous;
|
||||
/** Array of attributes. Last one should have its name set to NULL */
|
||||
struct iio_attribute *attributes;
|
||||
/** Called when needs to be enabled */
|
||||
int (*enable)(void *trig);
|
||||
/** Called when needs to be disabled */
|
||||
int (*disable)(void *trig);
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct iio_device
|
||||
* @brief Structure holding channels and attributes of a device.
|
||||
*/
|
||||
struct iio_device {
|
||||
/** Structure for existing initialized irq controllers. Has to be
|
||||
* set to NULL if there isn't any irq controller initialized. */
|
||||
struct no_os_irq_ctrl_desc *irq_desc;
|
||||
/** Device number of channels */
|
||||
uint16_t num_ch;
|
||||
/** List of channels */
|
||||
struct iio_channel *channels;
|
||||
/** Array of attributes. Last one should have its name set to NULL */
|
||||
struct iio_attribute *attributes;
|
||||
/** Array of attributes. Last one should have its name set to NULL */
|
||||
struct iio_attribute *debug_attributes;
|
||||
/** Array of attributes. Last one should have its name set to NULL */
|
||||
struct iio_attribute *buffer_attributes;
|
||||
/* Numbers of bytes will be:
|
||||
* samples * (storage_size_of_first_active_ch / 8) * nb_active_channels
|
||||
* DEPRECATED.
|
||||
*/
|
||||
int32_t (*read_dev)(void *dev, void *buff, uint32_t nb_samples);
|
||||
/* Numbers of bytes will be:
|
||||
* samples * (storage_size_of_first_active_ch / 8) * nb_active_channels
|
||||
* DEPRECATED.
|
||||
*/
|
||||
int32_t (*write_dev)(void *dev, void *buff, uint32_t nb_samples);
|
||||
|
||||
/* Bufer callbacks */
|
||||
/** Called before enabling buffer */
|
||||
int32_t (*pre_enable)(void *dev, uint32_t mask);
|
||||
/** Called after disabling buffer */
|
||||
int32_t (*post_disable)(void *dev);
|
||||
/** Called when buffer ready to transfer. Write/read to/from dev */
|
||||
int32_t (*submit)(struct iio_device_data *dev);
|
||||
/** Called after a trigger signal has been received by iio */
|
||||
int32_t (*trigger_handler)(struct iio_device_data *dev);
|
||||
|
||||
/* Read device register */
|
||||
int32_t (*debug_reg_read)(void *dev, uint32_t reg, uint32_t *readval);
|
||||
/* Write device register */
|
||||
int32_t (*debug_reg_write)(void *dev, uint32_t reg, uint32_t writeval);
|
||||
|
||||
};
|
||||
|
||||
#endif /* IIO_TYPES_H_ */
|
||||
@@ -0,0 +1,927 @@
|
||||
/***************************************************************************//**
|
||||
* @file iiod.c
|
||||
* @brief Nonblocking implementation of iiod.
|
||||
* @author Mihail Chindris (mihail.chindris@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2022(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "iiod.h"
|
||||
#include "iiod_private.h"
|
||||
|
||||
#include "no_os_error.h"
|
||||
#include "no_os_util.h"
|
||||
|
||||
#define SET_DUMMY_IF_NULL(func, dummy) ((func) ? (func) : (dummy))
|
||||
|
||||
static char delim[] = " \r\n";
|
||||
|
||||
|
||||
static const char *attr_types_strs[] = {
|
||||
[IIO_ATTR_TYPE_DEBUG] = "DEBUG",
|
||||
[IIO_ATTR_TYPE_BUFFER] = "BUFFER",
|
||||
[IIO_ATTR_TYPE_CH_OUT] = "OUTPUT",
|
||||
[IIO_ATTR_TYPE_CH_IN] = "INPUT"
|
||||
};
|
||||
|
||||
static struct iiod_str cmds[] = {
|
||||
[IIOD_CMD_HELP] = IIOD_STR("HELP"),
|
||||
[IIOD_CMD_EXIT] = IIOD_STR("EXIT"),
|
||||
[IIOD_CMD_PRINT] = IIOD_STR("PRINT"),
|
||||
[IIOD_CMD_VERSION] = IIOD_STR("VERSION"),
|
||||
[IIOD_CMD_TIMEOUT] = IIOD_STR("TIMEOUT"),
|
||||
[IIOD_CMD_OPEN] = IIOD_STR("OPEN"),
|
||||
[IIOD_CMD_CLOSE] = IIOD_STR("CLOSE"),
|
||||
[IIOD_CMD_READ] = IIOD_STR("READ"),
|
||||
[IIOD_CMD_WRITE] = IIOD_STR("WRITE"),
|
||||
[IIOD_CMD_READBUF] = IIOD_STR("READBUF"),
|
||||
[IIOD_CMD_WRITEBUF] = IIOD_STR("WRITEBUF"),
|
||||
[IIOD_CMD_GETTRIG] = IIOD_STR("GETTRIG"),
|
||||
[IIOD_CMD_SETTRIG] = IIOD_STR("SETTRIG"),
|
||||
[IIOD_CMD_SET] = IIOD_STR("SET")
|
||||
};
|
||||
static const uint32_t priority_array[] = {
|
||||
/* Order not tested, just personal expectation. Function can
|
||||
* be improved, this improvement is chosen for simplicity */
|
||||
IIOD_CMD_READBUF,
|
||||
IIOD_CMD_WRITEBUF,
|
||||
IIOD_CMD_READ,
|
||||
IIOD_CMD_WRITE,
|
||||
IIOD_CMD_OPEN,
|
||||
IIOD_CMD_CLOSE,
|
||||
IIOD_CMD_PRINT,
|
||||
IIOD_CMD_EXIT,
|
||||
IIOD_CMD_TIMEOUT,
|
||||
IIOD_CMD_VERSION,
|
||||
IIOD_CMD_GETTRIG,
|
||||
IIOD_CMD_SETTRIG,
|
||||
IIOD_CMD_HELP,
|
||||
IIOD_CMD_SET
|
||||
};
|
||||
|
||||
static_assert(NO_OS_ARRAY_SIZE(cmds) == NO_OS_ARRAY_SIZE(priority_array),
|
||||
"Arrays must have the same size");
|
||||
|
||||
/* Set res->cmd to corresponding cmd and return the processed length of buf */
|
||||
static int32_t parse_cmd(const char *token, struct comand_desc *res)
|
||||
{
|
||||
uint32_t i;
|
||||
struct iiod_str *cmd;
|
||||
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < NO_OS_ARRAY_SIZE(cmds); ++i) {
|
||||
cmd = &cmds[priority_array[i]];
|
||||
if (strcmp(token, cmd->str) == 0) {
|
||||
res->cmd = priority_array[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int32_t parse_num(const char *token, uint32_t *res, uint32_t base)
|
||||
{
|
||||
char *end_ptr;
|
||||
|
||||
*res = strtoul(token, &end_ptr, base);
|
||||
if (*res == 0 && *end_ptr != '\0')
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t iiod_parse_open(const char *token, struct comand_desc *res,
|
||||
char **ctx)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
|
||||
ret = parse_num(token, &res->sample_count, 10);
|
||||
if (NO_OS_IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
|
||||
token = strtok_r(NULL, delim, ctx);
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
|
||||
ret = parse_num(token, &res->mask, 16);
|
||||
if (NO_OS_IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
|
||||
res->cyclic = 0;
|
||||
token = strtok_r(NULL, delim, ctx);
|
||||
if (token) {
|
||||
if (strcmp(token, "CYCLIC") == 0)
|
||||
res->cyclic = 1;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t iiod_parse_set(const char *token, struct comand_desc *res,
|
||||
char **ctx)
|
||||
{
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
|
||||
if (strcmp(token, "BUFFERS_COUNT"))
|
||||
return -EINVAL;
|
||||
|
||||
token = strtok_r(NULL, delim, ctx);
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
|
||||
return parse_num(token, &res->count, 10);
|
||||
}
|
||||
|
||||
static int32_t iiod_parse_rw_attr(const char *token, struct comand_desc *res,
|
||||
char **ctx)
|
||||
{
|
||||
int32_t i;
|
||||
|
||||
res->type = IIO_ATTR_TYPE_DEVICE;
|
||||
if (token) {
|
||||
for (i = 0; i < IIO_ATTR_TYPE_DEVICE; ++i) {
|
||||
if (strcmp(token, attr_types_strs[i]) == 0) {
|
||||
token = strtok_r(NULL, delim, ctx);
|
||||
res->type = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (res->type == IIO_ATTR_TYPE_CH_IN ||
|
||||
res->type == IIO_ATTR_TYPE_CH_OUT) {
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
strncpy(res->channel, token, sizeof(res->channel));
|
||||
token = strtok_r(NULL, delim, ctx);
|
||||
}
|
||||
|
||||
if (res->cmd == IIOD_CMD_WRITE) {
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
|
||||
if (*token >= '0' && *token <= '9') {
|
||||
memset(res->attr, 0, sizeof(res->attr));
|
||||
|
||||
return parse_num(token, &res->bytes_count, 10);
|
||||
}
|
||||
|
||||
strncpy(res->attr, token, sizeof(res->attr));
|
||||
token = strtok_r(NULL, delim, ctx);
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
|
||||
return parse_num(token, &res->bytes_count, 10);
|
||||
}
|
||||
|
||||
if (token)
|
||||
strncpy(res->attr, token, sizeof(res->attr));
|
||||
else
|
||||
memset(res->attr, 0, sizeof(res->attr));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t iiod_parse_line(char *buf, struct comand_desc *res, char **ctx)
|
||||
{
|
||||
int32_t ret;
|
||||
char *token;
|
||||
|
||||
token = strtok_r(buf, delim, ctx);
|
||||
ret = parse_cmd(token, res);
|
||||
if (NO_OS_IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
|
||||
token = strtok_r(NULL, delim, ctx);
|
||||
/* Commands without device */
|
||||
switch (res->cmd) {
|
||||
case IIOD_CMD_HELP:
|
||||
case IIOD_CMD_EXIT:
|
||||
case IIOD_CMD_PRINT:
|
||||
case IIOD_CMD_VERSION:
|
||||
return 0;
|
||||
case IIOD_CMD_TIMEOUT:
|
||||
return parse_num(token, &res->timeout, 10);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
strncpy(res->device, token, sizeof(res->device));
|
||||
token = strtok_r(NULL, delim, ctx);
|
||||
switch (res->cmd) {
|
||||
case IIOD_CMD_CLOSE:
|
||||
case IIOD_CMD_GETTRIG:
|
||||
return 0;
|
||||
case IIOD_CMD_OPEN:
|
||||
return iiod_parse_open(token, res, ctx);
|
||||
case IIOD_CMD_READ:
|
||||
case IIOD_CMD_WRITE:
|
||||
return iiod_parse_rw_attr(token, res, ctx);
|
||||
case IIOD_CMD_READBUF:
|
||||
case IIOD_CMD_WRITEBUF:
|
||||
return parse_num(token, &res->bytes_count, 10);
|
||||
case IIOD_CMD_SETTRIG:
|
||||
if (token)
|
||||
strncpy(res->trigger, token, sizeof(res->trigger));
|
||||
else
|
||||
memset(res->trigger, 0, sizeof(res->trigger));
|
||||
|
||||
return 0;
|
||||
case IIOD_CMD_SET:
|
||||
return iiod_parse_set(token, res, ctx);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int dummy_open(struct iiod_ctx *ctx, const char *device,
|
||||
uint32_t samples, uint32_t mask, bool cyclic)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int dummy_close(struct iiod_ctx *ctx, const char *device)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int dummy_rw_attr(struct iiod_ctx *ctx, const char *device,
|
||||
struct iiod_attr *attr, char *buf, uint32_t len)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int dummy_rd_data(struct iiod_ctx *ctx, const char *device, char *buf,
|
||||
uint32_t bytes)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int dummy_wr_data(struct iiod_ctx *ctx, const char *device,
|
||||
const char *trig, uint32_t bytes)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int dummy_set_timeout(struct iiod_ctx *ctx, uint32_t timeout)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int dummy_set_buffers_count(struct iiod_ctx *ctx, const char *device,
|
||||
uint32_t buffers_count)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int32_t iiod_copy_ops(struct iiod_ops *ops, struct iiod_ops *new_ops)
|
||||
{
|
||||
if (!new_ops->recv || !new_ops->send)
|
||||
return -EINVAL;
|
||||
|
||||
ops->recv = new_ops->recv;
|
||||
ops->send = new_ops->send;
|
||||
|
||||
ops->open = SET_DUMMY_IF_NULL(new_ops->open, dummy_open);
|
||||
ops->close = SET_DUMMY_IF_NULL(new_ops->close, dummy_close);
|
||||
ops->read_buffer = SET_DUMMY_IF_NULL(new_ops->read_buffer, dummy_rd_data);
|
||||
ops->write_buffer = SET_DUMMY_IF_NULL(new_ops->write_buffer, dummy_wr_data);
|
||||
ops->read_attr = SET_DUMMY_IF_NULL(new_ops->read_attr, dummy_rw_attr);
|
||||
ops->write_attr = SET_DUMMY_IF_NULL(new_ops->write_attr, dummy_rw_attr);
|
||||
ops->get_trigger = SET_DUMMY_IF_NULL(new_ops->get_trigger, dummy_rd_data);
|
||||
ops->set_trigger = SET_DUMMY_IF_NULL(new_ops->set_trigger, dummy_wr_data);
|
||||
ops->set_timeout = SET_DUMMY_IF_NULL(new_ops->set_timeout, dummy_set_timeout);
|
||||
ops->set_buffers_count = SET_DUMMY_IF_NULL(new_ops->set_buffers_count,
|
||||
dummy_set_buffers_count);
|
||||
ops->refill_buffer = SET_DUMMY_IF_NULL(new_ops->refill_buffer,
|
||||
dummy_close);
|
||||
ops->push_buffer = SET_DUMMY_IF_NULL(new_ops->push_buffer,
|
||||
dummy_close);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t iiod_init(struct iiod_desc **desc, struct iiod_init_param *param)
|
||||
{
|
||||
struct iiod_desc *ldesc;
|
||||
int32_t ret;
|
||||
|
||||
if (!desc || !param || !param->ops)
|
||||
return -EINVAL;
|
||||
|
||||
ldesc = (struct iiod_desc *)calloc(1, sizeof(*ldesc));
|
||||
if (!ldesc)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = iiod_copy_ops(&ldesc->ops, param->ops);
|
||||
if (NO_OS_IS_ERR_VALUE(ret)) {
|
||||
free(ldesc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ldesc->xml = param->xml;
|
||||
ldesc->xml_len = param->xml_len;
|
||||
ldesc->app_instance = param->instance;
|
||||
ldesc->phy_type = param->phy_type;
|
||||
|
||||
*desc = ldesc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iiod_remove(struct iiod_desc *desc)
|
||||
{
|
||||
free(desc);
|
||||
}
|
||||
|
||||
static void conn_clean_state(struct iiod_conn_priv *conn)
|
||||
{
|
||||
memset(&conn->cmd_data, 0, sizeof(conn->cmd_data));
|
||||
memset(&conn->res, 0, sizeof(conn->res));
|
||||
memset(&conn->nb_buf, 0, sizeof(conn->nb_buf));
|
||||
|
||||
conn->res.buf.buf = NULL;
|
||||
conn->res.buf.idx = 0;
|
||||
conn->parser_idx = 0;
|
||||
conn->state = IIOD_READING_LINE;
|
||||
}
|
||||
|
||||
int32_t iiod_conn_add(struct iiod_desc *desc, struct iiod_conn_data *data,
|
||||
uint32_t *new_conn_id)
|
||||
{
|
||||
uint32_t i;
|
||||
struct iiod_conn_priv *conn;
|
||||
|
||||
if (!desc || !new_conn_id)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < IIOD_MAX_CONNECTIONS; ++i)
|
||||
if (!desc->conns[i].used) {
|
||||
conn = &desc->conns[i];
|
||||
memset(conn, 0, sizeof(*conn));
|
||||
conn->used = 1;
|
||||
conn->conn = data->conn;
|
||||
/*
|
||||
* TODO in future:
|
||||
* think of using other buffer (e.g. ciruclar_buffer)
|
||||
* to somehow implement zero copy
|
||||
*/
|
||||
conn->payload_buf = data->buf;
|
||||
conn->payload_buf_len = data->len;
|
||||
*new_conn_id = i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
int32_t iiod_conn_remove(struct iiod_desc *desc, uint32_t conn_id,
|
||||
struct iiod_conn_data *data)
|
||||
{
|
||||
if (!desc || conn_id > IIOD_MAX_CONNECTIONS ||
|
||||
!desc->conns[conn_id].used)
|
||||
return -EINVAL;
|
||||
struct iiod_conn_priv *conn;
|
||||
conn = &desc->conns[conn_id];
|
||||
data->conn = conn->conn;
|
||||
data->len = conn->payload_buf_len;
|
||||
data->buf = conn->payload_buf;
|
||||
conn->used = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t call_op(struct iiod_ops *ops, struct comand_desc *data,
|
||||
struct iiod_ctx *ctx)
|
||||
{
|
||||
switch (data->cmd) {
|
||||
case IIOD_CMD_HELP:
|
||||
return -EINVAL;
|
||||
case IIOD_CMD_TIMEOUT:
|
||||
return ops->set_timeout(ctx, data->timeout);
|
||||
case IIOD_CMD_OPEN:
|
||||
return ops->open(ctx, data->device, data->sample_count,
|
||||
data->mask, data->cyclic);
|
||||
case IIOD_CMD_CLOSE:
|
||||
return ops->close(ctx, data->device);
|
||||
case IIOD_CMD_SETTRIG:
|
||||
return ops->set_trigger(ctx, data->device, data->trigger,
|
||||
strlen(data->trigger));
|
||||
case IIOD_CMD_SET:
|
||||
return ops->set_buffers_count(ctx, data->device, data->count);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unload data from buf without blocking.
|
||||
* When done will return 0, if there is still data to be sent it will return
|
||||
* -EAGIAN. On error, an negative error code is returned
|
||||
*/
|
||||
static int32_t rw_iiod_buff(struct iiod_desc *desc, struct iiod_conn_priv *conn,
|
||||
struct iiod_buff *buf, uint8_t flags)
|
||||
{
|
||||
struct iiod_ctx ctx = IIOD_CTX(desc, conn);
|
||||
uint8_t *tmp_buf;
|
||||
int32_t ret;
|
||||
int32_t len;
|
||||
|
||||
len = buf->len - buf->idx;
|
||||
if (len) {
|
||||
tmp_buf = (uint8_t *)buf->buf + buf->idx;
|
||||
if (flags & IIOD_WR)
|
||||
ret = desc->ops.send(&ctx, tmp_buf, len);
|
||||
else
|
||||
ret = desc->ops.recv(&ctx, tmp_buf, len);
|
||||
if (NO_OS_IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
|
||||
buf->idx += ret;
|
||||
if (ret < len)
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (flags & IIOD_ENDL) {
|
||||
ret = desc->ops.send(&ctx, (uint8_t *)"\n", 1);
|
||||
if (NO_OS_IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
|
||||
if (ret != 1)
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t do_read_buff_delayed(struct iiod_desc *desc,
|
||||
struct iiod_conn_priv *conn)
|
||||
{
|
||||
struct iiod_ctx ctx = IIOD_CTX(desc, conn);
|
||||
uint32_t max_to_read;
|
||||
int32_t ret, len;
|
||||
|
||||
conn->nb_buf.buf = conn->payload_buf;
|
||||
len = no_os_min(conn->payload_buf_len, conn->cmd_data.bytes_count);
|
||||
max_to_read = len - conn->nb_buf.len;
|
||||
ret = desc->ops.read_buffer(&ctx, conn->cmd_data.device,
|
||||
conn->nb_buf.buf + conn->nb_buf.len, max_to_read);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
conn->nb_buf.len += ret;
|
||||
|
||||
if (conn->nb_buf.len < conn->cmd_data.bytes_count)
|
||||
return -EAGAIN;
|
||||
|
||||
ret = rw_iiod_buff(desc, conn, &conn->nb_buf, IIOD_WR);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
conn->nb_buf.len = 0;
|
||||
conn->nb_buf.idx = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t do_read_buff(struct iiod_desc *desc, struct iiod_conn_priv *conn)
|
||||
{
|
||||
struct iiod_ctx ctx;
|
||||
int32_t ret, len;
|
||||
|
||||
/*
|
||||
* When using the network backend wait for a whole buffer to be filled
|
||||
* before sending in order to reduce the ammount of network traffic.
|
||||
*/
|
||||
if (desc->phy_type == USE_NETWORK)
|
||||
return do_read_buff_delayed(desc, conn);
|
||||
|
||||
ctx = (struct iiod_ctx)IIOD_CTX(desc, conn);
|
||||
if (conn->nb_buf.len == 0) {
|
||||
conn->nb_buf.buf = conn->payload_buf;
|
||||
len = no_os_min(conn->payload_buf_len,
|
||||
conn->cmd_data.bytes_count);
|
||||
/* Read from dev */
|
||||
ret = desc->ops.read_buffer(&ctx, conn->cmd_data.device,
|
||||
conn->nb_buf.buf, len);
|
||||
if (NO_OS_IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
len = ret;
|
||||
conn->nb_buf.len = len;
|
||||
conn->nb_buf.idx = 0;
|
||||
}
|
||||
if (conn->nb_buf.idx < conn->nb_buf.len) {
|
||||
/* Write on conn */
|
||||
ret = rw_iiod_buff(desc, conn, &conn->nb_buf, IIOD_WR);
|
||||
if (NO_OS_IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
|
||||
conn->cmd_data.bytes_count -= conn->nb_buf.len;
|
||||
conn->nb_buf.len = 0;
|
||||
if (conn->cmd_data.bytes_count)
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t do_write_buff(struct iiod_desc *desc,
|
||||
struct iiod_conn_priv *conn)
|
||||
{
|
||||
struct iiod_ctx ctx = IIOD_CTX(desc, conn);
|
||||
int32_t ret, len;
|
||||
|
||||
if (conn->nb_buf.len == 0) {
|
||||
conn->nb_buf.buf = conn->payload_buf;
|
||||
len = no_os_min(conn->payload_buf_len,
|
||||
conn->cmd_data.bytes_count);
|
||||
conn->nb_buf.len = len;
|
||||
conn->nb_buf.idx = 0;
|
||||
}
|
||||
if (conn->nb_buf.idx < conn->nb_buf.len) {
|
||||
/* Read from conn */
|
||||
ret = rw_iiod_buff(desc, conn, &conn->nb_buf, IIOD_RD);
|
||||
if (NO_OS_IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
}
|
||||
/* Write to dev */
|
||||
ret = desc->ops.write_buffer(&ctx, conn->cmd_data.device,
|
||||
conn->nb_buf.buf, conn->nb_buf.len);
|
||||
if (NO_OS_IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
|
||||
conn->cmd_data.bytes_count -= conn->nb_buf.len;
|
||||
conn->nb_buf.len = 0;
|
||||
if (conn->cmd_data.bytes_count)
|
||||
return -EAGAIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t iiod_run_cmd(struct iiod_desc *desc,
|
||||
struct iiod_conn_priv *conn)
|
||||
{
|
||||
struct iiod_ctx ctx = IIOD_CTX(desc, conn);
|
||||
struct comand_desc *data = &conn->cmd_data;
|
||||
struct iiod_attr attr = {
|
||||
.type = data->type,
|
||||
.name = data->attr,
|
||||
.channel = data->channel
|
||||
};
|
||||
int32_t ret;
|
||||
|
||||
switch (data->cmd) {
|
||||
case IIOD_CMD_HELP:
|
||||
case IIOD_CMD_TIMEOUT:
|
||||
case IIOD_CMD_OPEN:
|
||||
case IIOD_CMD_CLOSE:
|
||||
case IIOD_CMD_SETTRIG:
|
||||
case IIOD_CMD_SET:
|
||||
if (data->cmd == IIOD_CMD_OPEN) {
|
||||
conn->mask = data->mask;
|
||||
if (data->cyclic)
|
||||
conn->is_cyclic_buffer = true;
|
||||
}
|
||||
if (data->cmd == IIOD_CMD_CLOSE)
|
||||
/* Set is_cyclic_buffer to false every time the device is closed */
|
||||
conn->is_cyclic_buffer = false;
|
||||
conn->res.val = call_op(&desc->ops, data, &ctx);
|
||||
conn->res.write_val = 1;
|
||||
break;
|
||||
case IIOD_CMD_EXIT:
|
||||
conn->res.val = 0;
|
||||
conn->res.write_val = 1;
|
||||
|
||||
return -ENOTCONN;
|
||||
case IIOD_CMD_PRINT:
|
||||
conn->res.val = desc->xml_len;
|
||||
conn->res.write_val = 1;
|
||||
conn->res.buf.buf = desc->xml;
|
||||
conn->res.buf.len = desc->xml_len;
|
||||
break;
|
||||
case IIOD_CMD_VERSION:
|
||||
conn->res.buf.buf = IIOD_VERSION;
|
||||
conn->res.buf.len = IIOD_VERSION_LEN;
|
||||
break;
|
||||
case IIOD_CMD_READ:
|
||||
case IIOD_CMD_GETTRIG:
|
||||
if (data->cmd == IIOD_CMD_READ)
|
||||
ret = desc->ops.read_attr(&ctx, data->device, &attr,
|
||||
conn->payload_buf,
|
||||
conn->payload_buf_len);
|
||||
else
|
||||
ret = desc->ops.get_trigger(&ctx, data->device,
|
||||
conn->payload_buf,
|
||||
conn->payload_buf_len);
|
||||
conn->res.val = ret;
|
||||
conn->res.write_val = 1;
|
||||
if (!NO_OS_IS_ERR_VALUE(ret)) {
|
||||
conn->res.buf.buf = conn->payload_buf;
|
||||
conn->res.buf.len = ret;
|
||||
}
|
||||
break;
|
||||
case IIOD_CMD_WRITE:
|
||||
conn->payload_buf[data->bytes_count] = '\0';
|
||||
ret = desc->ops.write_attr(&ctx, data->device, &attr,
|
||||
conn->payload_buf,
|
||||
data->bytes_count);
|
||||
conn->nb_buf.len = 0;
|
||||
conn->res.val = ret;
|
||||
conn->res.write_val = 1;
|
||||
break;
|
||||
case IIOD_CMD_READBUF:
|
||||
conn->res.write_val = 1;
|
||||
ret = desc->ops.refill_buffer(&ctx, data->device);
|
||||
if (NO_OS_IS_ERR_VALUE(ret)) {
|
||||
conn->res.val = ret;
|
||||
break;
|
||||
}
|
||||
conn->res.val = data->bytes_count;
|
||||
ret = snprintf(conn->buf_mask, 10, "%08"PRIx32, conn->mask);
|
||||
conn->res.buf.buf = conn->buf_mask;
|
||||
conn->res.buf.len = ret;
|
||||
break;
|
||||
case IIOD_CMD_WRITEBUF:
|
||||
conn->res.val = data->bytes_count;
|
||||
conn->res.write_val = 1;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t iiod_read_line(struct iiod_desc *desc,
|
||||
struct iiod_conn_priv *conn)
|
||||
{
|
||||
struct iiod_ctx ctx = {
|
||||
.instance = desc->app_instance,
|
||||
.conn = conn->conn
|
||||
};
|
||||
int32_t ret;
|
||||
char *ch;
|
||||
|
||||
while (conn->parser_idx < IIOD_PARSER_MAX_BUF_SIZE - 1) {
|
||||
ch = conn->parser_buf + conn->parser_idx;
|
||||
ret = desc->ops.recv(&ctx, (uint8_t *)ch, 1);
|
||||
if (ret == -EAGAIN || ret == 0)
|
||||
return -EAGAIN;
|
||||
|
||||
if (NO_OS_IS_ERR_VALUE(ret))
|
||||
goto end;
|
||||
|
||||
if (conn->parser_idx == 0 && (*ch == '\n' || *ch == '\r'))
|
||||
continue ;
|
||||
|
||||
++conn->parser_idx;
|
||||
if (*ch == '\n') {
|
||||
conn->parser_buf[conn->parser_idx] = '\0';
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
ret = -EIO;
|
||||
end:
|
||||
conn->parser_idx = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function will return SUCCESS when a state was processed.
|
||||
* If a state is still in processing state, it will return -EAGAIN.
|
||||
* If other error occur. E.g. Connection errors, they are returned and
|
||||
* the connection must be cleaned up.
|
||||
*/
|
||||
static int32_t iiod_run_state(struct iiod_desc *desc,
|
||||
struct iiod_conn_priv *conn)
|
||||
{
|
||||
struct iiod_ctx ctx = {
|
||||
.instance = desc->app_instance,
|
||||
.conn = conn->conn
|
||||
};
|
||||
int32_t ret;
|
||||
|
||||
switch (conn->state) {
|
||||
case IIOD_READING_LINE:
|
||||
/* Read input data until \n. I/O Calls */
|
||||
ret = iiod_read_line(desc, conn);
|
||||
if (NO_OS_IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
|
||||
/* Fill struct comand_desc with data from line. No I/O */
|
||||
ret = iiod_parse_line(conn->parser_buf, &conn->cmd_data,
|
||||
&conn->strtok_ctx);
|
||||
if (NO_OS_IS_ERR_VALUE(ret)) {
|
||||
/* Parsing line failed */
|
||||
conn->res.write_val = 1;
|
||||
conn->res.val = ret;
|
||||
conn->state = IIOD_WRITING_CMD_RESULT;
|
||||
} else if (conn->cmd_data.cmd == IIOD_CMD_WRITE) {
|
||||
/* Special case. Attribute needs to be read */
|
||||
conn->nb_buf.buf = conn->payload_buf;
|
||||
conn->nb_buf.len = conn->cmd_data.bytes_count;
|
||||
conn->nb_buf.idx = 0;
|
||||
conn->state = IIOD_READING_WRITE_DATA;
|
||||
} else {
|
||||
conn->state = IIOD_RUNNING_CMD;
|
||||
}
|
||||
|
||||
return 0;
|
||||
case IIOD_RUNNING_CMD:
|
||||
/* Execute or call necessary ops depending on cmd. No I/O */
|
||||
ret = iiod_run_cmd(desc, conn);
|
||||
if (NO_OS_IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
|
||||
conn->state = IIOD_WRITING_CMD_RESULT;
|
||||
|
||||
return 0;
|
||||
case IIOD_WRITING_CMD_RESULT:
|
||||
/* Write result or the length of data to be sent*/
|
||||
if (conn->res.write_val) {
|
||||
if (conn->nb_buf.len == 0) {
|
||||
conn->nb_buf.buf = conn->parser_buf;
|
||||
ret = sprintf(conn->nb_buf.buf, "%"PRIi32,
|
||||
conn->res.val);
|
||||
conn->nb_buf.len = ret;
|
||||
conn->nb_buf.idx = 0;
|
||||
}
|
||||
/* Non-blocking. Will enter here until val is sent */
|
||||
if (conn->nb_buf.idx < conn->nb_buf.len) {
|
||||
ret = rw_iiod_buff(desc, conn, &conn->nb_buf,
|
||||
IIOD_WR | IIOD_ENDL);
|
||||
if (NO_OS_IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/* Send buf from result. Non blocking */
|
||||
if (conn->res.buf.buf &&
|
||||
conn->res.buf.idx < conn->res.buf.len) {
|
||||
ret = rw_iiod_buff(desc, conn, &conn->res.buf,
|
||||
IIOD_WR | IIOD_ENDL);
|
||||
if (NO_OS_IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (conn->cmd_data.cmd != IIOD_CMD_READBUF &&
|
||||
conn->cmd_data.cmd != IIOD_CMD_WRITEBUF) {
|
||||
if (conn->is_cyclic_buffer && conn->cmd_data.cmd != IIOD_CMD_OPEN)
|
||||
conn->state = IIOD_PUSH_CYCLIC_BUFFER;
|
||||
else
|
||||
conn->state = IIOD_LINE_DONE;
|
||||
} else {
|
||||
/* Preapre for IIOD_RW_BUF state */
|
||||
memset(&conn->nb_buf, 0, sizeof(conn->nb_buf));
|
||||
conn->state = IIOD_RW_BUF;
|
||||
}
|
||||
|
||||
return 0;
|
||||
case IIOD_RW_BUF:
|
||||
/* IIOD_CMD_READBUF and IIOD_CMD_WRITEBUF special case */
|
||||
/* Non blocking read/write until all data is processed */
|
||||
if (conn->cmd_data.cmd == IIOD_CMD_READBUF)
|
||||
ret = do_read_buff(desc, conn);
|
||||
else {
|
||||
ret = do_write_buff(desc, conn);
|
||||
if (ret == 0) {
|
||||
conn->res.write_val = 1;
|
||||
ret = desc->ops.push_buffer(&ctx,
|
||||
conn->cmd_data.device);
|
||||
if (NO_OS_IS_ERR_VALUE(ret)) {
|
||||
conn->res.val = ret;
|
||||
conn->state = IIOD_LINE_DONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
memset(&conn->res.buf, 0, sizeof(conn->res.buf));
|
||||
conn->res.val = conn->cmd_data.bytes_count;
|
||||
conn->cmd_data.cmd = IIOD_CMD_PRINT;
|
||||
conn->state = IIOD_WRITING_CMD_RESULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (NO_OS_IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
|
||||
conn->state = IIOD_LINE_DONE;
|
||||
|
||||
return 0;
|
||||
case IIOD_READING_WRITE_DATA:
|
||||
/* Read attribute */
|
||||
ret = rw_iiod_buff(desc, conn, &conn->nb_buf, IIOD_RD);
|
||||
if (NO_OS_IS_ERR_VALUE(ret))
|
||||
return ret;
|
||||
|
||||
conn->state = IIOD_RUNNING_CMD;
|
||||
|
||||
return 0;
|
||||
case IIOD_PUSH_CYCLIC_BUFFER:
|
||||
/* Push puffer to IIO application */
|
||||
ret = desc->ops.push_buffer(&ctx,
|
||||
conn->cmd_data.device);
|
||||
/* If an error was encountered, close connection */
|
||||
if (NO_OS_IS_ERR_VALUE(ret)) {
|
||||
conn->res.val = ret;
|
||||
desc->ops.close(&ctx, conn->cmd_data.device);
|
||||
conn->state = IIOD_LINE_DONE;
|
||||
conn->is_cyclic_buffer = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read data from the client to verify whether a close command has been sent */
|
||||
ret = iiod_read_line(desc, conn);
|
||||
if (NO_OS_IS_ERR_VALUE(ret))
|
||||
return 0;
|
||||
|
||||
/* Fill struct comand_desc with data from line */
|
||||
ret = iiod_parse_line(conn->parser_buf, &conn->cmd_data,
|
||||
&conn->strtok_ctx);
|
||||
if (!NO_OS_IS_ERR_VALUE(ret) && conn->cmd_data.cmd == IIOD_CMD_CLOSE) {
|
||||
/* Exit this state only if a close command is received
|
||||
All other commands will be ignored.
|
||||
*/
|
||||
conn->nb_buf.len = 0;
|
||||
conn->state = IIOD_RUNNING_CMD;
|
||||
conn->is_cyclic_buffer = false;
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
/* Should never get here */
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t iiod_conn_step(struct iiod_desc *desc, uint32_t conn_id)
|
||||
{
|
||||
struct iiod_conn_priv *conn;
|
||||
int32_t ret;
|
||||
|
||||
if (!desc || conn_id > IIOD_MAX_CONNECTIONS ||
|
||||
!desc->conns[conn_id].used)
|
||||
return -EINVAL;
|
||||
|
||||
conn = &desc->conns[conn_id];
|
||||
do {
|
||||
ret = iiod_run_state(desc, conn);
|
||||
if (ret == -EAGAIN)
|
||||
return ret;
|
||||
if (NO_OS_IS_ERR_VALUE(ret) || conn->state == IIOD_LINE_DONE)
|
||||
break;
|
||||
//The loop will continue because the state was changed.
|
||||
} while (true);
|
||||
|
||||
conn_clean_state(conn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
/***************************************************************************//**
|
||||
* @file iiod.h
|
||||
* @brief Header file of iiod
|
||||
* @author Mihail Chindris (mihail.chindris@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2022(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef IIOD_H
|
||||
#define IIOD_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "iio.h"
|
||||
|
||||
/* Maximum nomber of iiod connections to allocate simultaneously */
|
||||
#define IIOD_MAX_CONNECTIONS 10
|
||||
#define IIOD_VERSION "1.1.0000000"
|
||||
#define IIOD_VERSION_LEN (sizeof(IIOD_VERSION) - 1)
|
||||
|
||||
#define MAX_DEV_ID 64
|
||||
#define MAX_TRIG_ID 64
|
||||
#define MAX_CHN_ID 64
|
||||
#define MAX_ATTR_NAME 256
|
||||
|
||||
enum iio_attr_type {
|
||||
IIO_ATTR_TYPE_DEBUG,
|
||||
IIO_ATTR_TYPE_BUFFER,
|
||||
IIO_ATTR_TYPE_CH_OUT,
|
||||
IIO_ATTR_TYPE_CH_IN,
|
||||
IIO_ATTR_TYPE_DEVICE,
|
||||
};
|
||||
|
||||
struct iiod_attr {
|
||||
enum iio_attr_type type;
|
||||
/*
|
||||
* Attribute name.
|
||||
* If empty (""), all attributes of the specified iio_attr_type must
|
||||
* be read/wrote
|
||||
*/
|
||||
const char *name;
|
||||
const char *channel;
|
||||
};
|
||||
|
||||
struct iiod_ctx {
|
||||
/* Value specified in iiod_init_param.instance in iiod_init */
|
||||
void *instance;
|
||||
/* Value specified in iiod_conn_data.conn in iiod_conn_add */
|
||||
void *conn;
|
||||
};
|
||||
|
||||
struct iiod_conn_data {
|
||||
/* Value to be used in iiod_ctx */
|
||||
void *conn;
|
||||
/* Buffer to store attributes or buffer data for a connection. */
|
||||
char *buf;
|
||||
/* Size of the provided buffer. It must fit the max attribute size */
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
/* Functions should return a negative error code on failure */
|
||||
struct iiod_ops {
|
||||
/*
|
||||
* I/O operations
|
||||
* Send and recv are used to send or receive data to/from a connection.
|
||||
* They should send/receive the at maximum len bytes.
|
||||
* They must return the number of bytes sent/received.
|
||||
* They can return 0 or -EAGAIN when no data was processed.
|
||||
* They can do not block. They will be called again if there is still
|
||||
* data to be sent/recevied
|
||||
*/
|
||||
int (*send)(struct iiod_ctx *ctx, uint8_t *buf, uint32_t len);
|
||||
int (*recv)(struct iiod_ctx *ctx, uint8_t *buf, uint32_t len);
|
||||
|
||||
/*
|
||||
* This is the equivalent of libiio iio_device_create_buffer.
|
||||
* Called in order to create a buffer to read or write data.
|
||||
* read_buffer or write_buffer will follow with a maximum of samples
|
||||
* (depending on the internal buffer).
|
||||
* All calls with the same ctx will refer to this buffer until close is
|
||||
* called.
|
||||
*/
|
||||
int (*open)(struct iiod_ctx *ctx, const char *device, uint32_t samples,
|
||||
uint32_t mask, bool cyclic);
|
||||
/* Equivalent of iio_buffer_destroy */
|
||||
int (*close)(struct iiod_ctx *ctx, const char *device);
|
||||
|
||||
/* Read data from opened buffer */
|
||||
int (*read_buffer)(struct iiod_ctx *ctx, const char *device, char *buf,
|
||||
uint32_t bytes);
|
||||
/* Called to notify that buffer must be refiiled */
|
||||
int (*refill_buffer)(struct iiod_ctx *ctx, const char *device);
|
||||
|
||||
/* Write data to opened buffer */
|
||||
int (*write_buffer)(struct iiod_ctx *ctx, const char *device,
|
||||
const char *buf, uint32_t bytes);
|
||||
/* Called to notify that buffer must be pushed to hardware */
|
||||
int (*push_buffer)(struct iiod_ctx *ctx, const char *device);
|
||||
|
||||
/*
|
||||
* Attribute has to be read in buf and return the number of bytes
|
||||
* written.
|
||||
*/
|
||||
int (*read_attr)(struct iiod_ctx *ctx, const char *device,
|
||||
struct iiod_attr *attr, char *buf, uint32_t len);
|
||||
/* Attribute buf is filled with the attribute value. */
|
||||
int (*write_attr)(struct iiod_ctx *ctx, const char *device,
|
||||
struct iiod_attr *attr, char *buf, uint32_t len);
|
||||
/* Simular with read_attr but trigger must be filled */
|
||||
int (*get_trigger)(struct iiod_ctx *ctx, const char *device,
|
||||
char *trigger, uint32_t len);
|
||||
/*
|
||||
* Simular with write_attr but trigger name is in trigger.
|
||||
* If trigger is equals to "". Trigger must be removed.
|
||||
*/
|
||||
int (*set_trigger)(struct iiod_ctx *ctx, const char *device,
|
||||
const char *trigger, uint32_t len);
|
||||
|
||||
/* I don't know what this should be used for :) */
|
||||
int (*set_timeout)(struct iiod_ctx *ctx, uint32_t timeout);
|
||||
|
||||
/* I don't know what this should be used for :) */
|
||||
int (*set_buffers_count)(struct iiod_ctx *ctx, const char *device,
|
||||
uint32_t buffers_count);
|
||||
};
|
||||
|
||||
/*
|
||||
* Internal structure.
|
||||
* It is created in iiod_init and must be passed to all fucntions
|
||||
*/
|
||||
struct iiod_desc;
|
||||
|
||||
/* Parameter to initialize iiod_desc */
|
||||
struct iiod_init_param {
|
||||
struct iiod_ops *ops;
|
||||
/* Value to be send in each iiod_ctx from iiod_ops functions */
|
||||
void *instance;
|
||||
/*
|
||||
* Xml description of the context and devices. It should exist until
|
||||
* iiod_remove is called
|
||||
*/
|
||||
char *xml;
|
||||
/* Size of xml in bytes */
|
||||
uint32_t xml_len;
|
||||
/* Backend used by IIOD */
|
||||
enum physical_link_type phy_type;
|
||||
};
|
||||
|
||||
/* Initialize desc. */
|
||||
int32_t iiod_init(struct iiod_desc **desc, struct iiod_init_param *param);
|
||||
/* Remove desc resources */
|
||||
void iiod_remove(struct iiod_desc *desc);
|
||||
|
||||
/*
|
||||
* Notify iiod about a new connection in order to store context for it.
|
||||
* new_conn_id is set in order to reference the connection in iiod_conn_step
|
||||
*/
|
||||
int32_t iiod_conn_add(struct iiod_desc *desc, struct iiod_conn_data *data,
|
||||
uint32_t *new_conn_id);
|
||||
/* Remove conn_id from iiod. Provided data is returned in data */
|
||||
int32_t iiod_conn_remove(struct iiod_desc *desc, uint32_t conn_id,
|
||||
struct iiod_conn_data *data);
|
||||
/* Advance in the state machine of a connection. Will not block */
|
||||
int32_t iiod_conn_step(struct iiod_desc *desc, uint32_t conn_id);
|
||||
|
||||
#endif //IIOD_H
|
||||
@@ -0,0 +1,178 @@
|
||||
/***************************************************************************//**
|
||||
* @file iiod_private.h
|
||||
* @brief Private header file of iiod
|
||||
* @author Mihail Chindris (mihail.chindris@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2022(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef IIOD_PRIVATE_H
|
||||
#define IIOD_PRIVATE_H
|
||||
|
||||
#include "iio.h"
|
||||
|
||||
#define IIOD_WR 0x1
|
||||
#define IIOD_ENDL 0x2
|
||||
#define IIOD_RD 0x4
|
||||
#define IIOD_PARSER_MAX_BUF_SIZE 128
|
||||
|
||||
#define IIOD_STR(cmd) {(cmd), sizeof(cmd) - 1}
|
||||
|
||||
#define IIOD_CTX(desc, conn) {.instance = (desc)->app_instance,\
|
||||
.conn = (conn)->conn}
|
||||
|
||||
|
||||
/* Used to store a string and its size */
|
||||
struct iiod_str {
|
||||
char *str;
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
/*
|
||||
* Commads are the ones documented int the link:
|
||||
* https://wiki.analog.com/resources/tools-software/linux-software/libiio_internals#the_network_backend_and_iio_daemon
|
||||
*/
|
||||
enum iiod_cmd {
|
||||
IIOD_CMD_HELP,
|
||||
IIOD_CMD_EXIT,
|
||||
IIOD_CMD_PRINT,
|
||||
IIOD_CMD_VERSION,
|
||||
IIOD_CMD_TIMEOUT,
|
||||
IIOD_CMD_OPEN,
|
||||
IIOD_CMD_CLOSE,
|
||||
IIOD_CMD_READ,
|
||||
IIOD_CMD_WRITE,
|
||||
IIOD_CMD_READBUF,
|
||||
IIOD_CMD_WRITEBUF,
|
||||
IIOD_CMD_GETTRIG,
|
||||
IIOD_CMD_SETTRIG,
|
||||
IIOD_CMD_SET
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure to be filled after a command is parsed.
|
||||
* Depending of cmd some fields are set or not
|
||||
*/
|
||||
struct comand_desc {
|
||||
enum iiod_cmd cmd;
|
||||
uint32_t mask;
|
||||
uint32_t timeout;
|
||||
uint32_t sample_count;
|
||||
uint32_t bytes_count;
|
||||
uint32_t count;
|
||||
bool cyclic;
|
||||
char device[MAX_DEV_ID];
|
||||
char channel[MAX_CHN_ID];
|
||||
char attr[MAX_ATTR_NAME];
|
||||
char trigger[MAX_TRIG_ID];
|
||||
enum iio_attr_type type;
|
||||
};
|
||||
|
||||
/* Used to store buffer indexes for non blocking transfers */
|
||||
struct iiod_buff {
|
||||
char *buf;
|
||||
uint32_t idx;
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
/* Result after executing a command. */
|
||||
struct iiod_run_cmd_result {
|
||||
uint32_t val;
|
||||
/* If set. Val needs to be sent */
|
||||
bool write_val;
|
||||
/* If buf.len != 0 buf has to be sent */
|
||||
struct iiod_buff buf;
|
||||
};
|
||||
|
||||
/* Internal structure to handle a connection state */
|
||||
struct iiod_conn_priv {
|
||||
/* User instance of the connection to be sent in iiod_ctx */
|
||||
void *conn;
|
||||
/* Unset when can be used from the connection pool */
|
||||
bool used;
|
||||
|
||||
/* Command data after parsed */
|
||||
struct comand_desc cmd_data;
|
||||
/* Result of an executed cmd */
|
||||
struct iiod_run_cmd_result res;
|
||||
/* IIOD States */
|
||||
enum {
|
||||
/* Reading line until \n */
|
||||
IIOD_READING_LINE,
|
||||
/* Execut cmd without I/O operations */
|
||||
IIOD_RUNNING_CMD,
|
||||
/* Write result of executed cmd */
|
||||
IIOD_WRITING_CMD_RESULT,
|
||||
/* I/O operations for READBUF and WRITEBUF cmds */
|
||||
IIOD_RW_BUF,
|
||||
/* I/O operations for WRITE cmd */
|
||||
IIOD_READING_WRITE_DATA,
|
||||
/* Set when a operation is finalized */
|
||||
IIOD_LINE_DONE,
|
||||
/* Pushing cyclic buffer until IIO device is closed */
|
||||
IIOD_PUSH_CYCLIC_BUFFER,
|
||||
} state;
|
||||
|
||||
/* Buffer to store received line */
|
||||
char parser_buf[IIOD_PARSER_MAX_BUF_SIZE];
|
||||
/* Index in parser_buf. For nonblocking operation */
|
||||
uint32_t parser_idx;
|
||||
/* Buffer to store raw data (attributes or buffer data).*/
|
||||
char *payload_buf;
|
||||
/* Length of payload_buf_len */
|
||||
uint32_t payload_buf_len;
|
||||
/* Used in nonbloking transfers to save indexes */
|
||||
struct iiod_buff nb_buf;
|
||||
|
||||
/* Mask of current opened buffer */
|
||||
uint32_t mask;
|
||||
/* Buffer to store mask as a string */
|
||||
char buf_mask[10];
|
||||
/* Context for strtok_r function */
|
||||
char *strtok_ctx;
|
||||
/* True if the device was open with cyclic buffer flag */
|
||||
bool is_cyclic_buffer;
|
||||
};
|
||||
|
||||
/* Private iiod information */
|
||||
struct iiod_desc {
|
||||
/* Pool of iiod connections */
|
||||
struct iiod_conn_priv conns[IIOD_MAX_CONNECTIONS];
|
||||
/* Application operations */
|
||||
struct iiod_ops ops;
|
||||
/* Application instance */
|
||||
void *app_instance;
|
||||
/* Address of xml */
|
||||
char *xml;
|
||||
/* XML length in bytes */
|
||||
uint32_t xml_len;
|
||||
/* Backend used by IIOD */
|
||||
enum physical_link_type phy_type;
|
||||
};
|
||||
|
||||
#endif //IIOD_PRIVATE_H
|
||||
@@ -0,0 +1,295 @@
|
||||
/**
|
||||
* The JESD204 framework
|
||||
*
|
||||
* Copyright (c) 2022 Analog Devices Inc.
|
||||
*/
|
||||
#ifndef _JESD204_H_
|
||||
#define _JESD204_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct jesd204_dev;
|
||||
|
||||
enum jesd204_subclass {
|
||||
JESD204_SUBCLASS_0,
|
||||
JESD204_SUBCLASS_1,
|
||||
JESD204_SUBCLASS_2,
|
||||
};
|
||||
|
||||
enum jesd204_version {
|
||||
JESD204_VERSION_A,
|
||||
JESD204_VERSION_B,
|
||||
JESD204_VERSION_C,
|
||||
};
|
||||
|
||||
/* JESD204C Supported encoding scheme */
|
||||
enum jesd204_encoder {
|
||||
JESD204_ENCODER_UNKNOWN,
|
||||
JESD204_ENCODER_8B10B,
|
||||
JESD204_ENCODER_64B66B,
|
||||
JESD204_ENCODER_64B80B,
|
||||
|
||||
JESD204_ENCODER_MAX
|
||||
};
|
||||
|
||||
enum jesd204_sysref_mode {
|
||||
JESD204_SYSREF_DISABLED,
|
||||
JESD204_SYSREF_CONTINUOUS,
|
||||
JESD204_SYSREF_ONESHOT,
|
||||
};
|
||||
|
||||
enum jesd204_state_change_result {
|
||||
JESD204_STATE_CHANGE_ERROR = -1,
|
||||
JESD204_STATE_CHANGE_DEFER = 0,
|
||||
JESD204_STATE_CHANGE_DONE,
|
||||
};
|
||||
|
||||
#define JESD204_LINKS_ALL ((unsigned int)(-1))
|
||||
|
||||
#define JESD204_LMFC_OFFSET_UNINITIALIZED ((uint16_t)-1)
|
||||
|
||||
/** @struct jesd204_sysref
|
||||
* @brief JESD204 parameters for SYSREF
|
||||
* @param mode: SYSREF mode (see jesd204_sysref_mode)
|
||||
* @param capture_falling_edge: true if it should capture falling edge
|
||||
* @param valid_falling_edge: true if falling edge should be valid
|
||||
* @param lmfc_offset: offset for LMFC
|
||||
*/
|
||||
struct jesd204_sysref {
|
||||
enum jesd204_sysref_mode mode;
|
||||
uint8_t capture_falling_edge;
|
||||
uint8_t valid_falling_edge;
|
||||
uint16_t lmfc_offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct jesd204_link
|
||||
* @brief JESD204 link configuration settings
|
||||
* @param link_id: JESD204 link ID provided via DT configuration
|
||||
* @param error: error code for this JESD204 link
|
||||
* @param is_transmit: true if this link is transmit (digital to analog)
|
||||
* @param sample_rate: sample rate for the link
|
||||
* @param sample_rate_div: optional sample rate divider for the link
|
||||
* final rate = sample_rate / sample_rate_div
|
||||
* @param num_lanes: number of JESD204 lanes (L)
|
||||
* @param num_converters: number of converters per link (M)
|
||||
* @param octets_per_frame: number of octets per frame (F)
|
||||
* @param frames_per_multiframe: number of frames per frame (K)
|
||||
* @param num_of_multiblocks_in_emb: number of multiblocks in extended multiblock (E) (JESD204C)
|
||||
* @param bits_per_sample: number of bits per sample (N')
|
||||
* @param converter_resolution: converter resolution (N)
|
||||
* @param jesd_version: JESD204 version (A, B or C) (JESDV)
|
||||
* @param jesd_encoder: JESD204C encoder (8B10B, 64B66B, 64B80B)
|
||||
* @param subclass: JESD204 subclass (0,1 or 2) (SUBCLASSV)
|
||||
* @param device_id: device ID (DID)
|
||||
* @param bank_id: bank ID (BID)
|
||||
* @param scrambling: true if scrambling enabled (SCR)
|
||||
* @param high_density: true if high-density format is used (HD)
|
||||
* @param ctrl_words_per_frame_clk: number of control words per frame clock
|
||||
* period (CF)
|
||||
* @param ctrl_bits_per_sample: number of control bits per sample (CS)
|
||||
* @param samples_per_conv_frame: number of samples per converter per frame
|
||||
* cycle (S)
|
||||
* @param lane_ids: array of lane IDs (LID); note that this is an
|
||||
* array the size of num_lanes
|
||||
* @param sysref: JESD204 sysref config, see jesd204_sysref
|
||||
* @param dac_adj_resolution_steps: number of adjustment resolution steps to adjust
|
||||
* DAC LMFC (ADJCNT) - Subclass 2 only
|
||||
* @param dac_adj_direction: direction to adjust DAC LMFC (ADJDIR)
|
||||
* Subclass 2 only
|
||||
* @param dac_phase_adj: true to do phase adjustment request to DAC
|
||||
* Subclass 2 only
|
||||
*/
|
||||
struct jesd204_link {
|
||||
uint32_t link_id;
|
||||
int error;
|
||||
|
||||
uint64_t sample_rate;
|
||||
uint32_t sample_rate_div;
|
||||
|
||||
bool is_transmit;
|
||||
|
||||
uint8_t num_lanes;
|
||||
uint8_t num_converters;
|
||||
uint8_t octets_per_frame;
|
||||
uint16_t frames_per_multiframe;
|
||||
uint8_t num_of_multiblocks_in_emb; /* E */
|
||||
|
||||
uint8_t bits_per_sample;
|
||||
|
||||
uint8_t converter_resolution;
|
||||
uint8_t jesd_version;
|
||||
uint8_t jesd_encoder;
|
||||
uint8_t subclass;
|
||||
|
||||
uint8_t device_id;
|
||||
uint8_t bank_id;
|
||||
|
||||
uint8_t scrambling;
|
||||
uint8_t high_density;
|
||||
|
||||
uint8_t ctrl_words_per_frame_clk;
|
||||
uint8_t ctrl_bits_per_sample;
|
||||
uint8_t samples_per_conv_frame;
|
||||
|
||||
uint8_t *lane_ids;
|
||||
|
||||
struct jesd204_sysref sysref;
|
||||
|
||||
/* Subclass 2 only */
|
||||
uint8_t dac_adj_resolution_steps;
|
||||
uint8_t dac_adj_direction;
|
||||
uint8_t dac_phase_adj;
|
||||
};
|
||||
|
||||
enum jesd204_state_op_reason {
|
||||
JESD204_STATE_OP_REASON_INIT,
|
||||
JESD204_STATE_OP_REASON_UNINIT,
|
||||
};
|
||||
|
||||
static inline const char *jesd204_state_op_reason_str(enum
|
||||
jesd204_state_op_reason reason)
|
||||
{
|
||||
switch (reason) {
|
||||
case JESD204_STATE_OP_REASON_INIT:
|
||||
return "initialization";
|
||||
case JESD204_STATE_OP_REASON_UNINIT:
|
||||
return "uninitialization";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
typedef int (*jesd204_sysref_cb)(struct jesd204_dev *jdev);
|
||||
|
||||
typedef int (*jesd204_dev_cb)(struct jesd204_dev *jdev,
|
||||
enum jesd204_state_op_reason reason);
|
||||
|
||||
typedef int (*jesd204_link_cb)(struct jesd204_dev *jdev,
|
||||
enum jesd204_state_op_reason,
|
||||
struct jesd204_link *lnk);
|
||||
|
||||
enum jesd204_state_op_mode {
|
||||
JESD204_STATE_OP_MODE_PER_LINK,
|
||||
JESD204_STATE_OP_MODE_PER_DEVICE,
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct jesd204_state_op
|
||||
* @brief JESD204 device per-state op
|
||||
* @param mode: mode for this state op, depending on this per_device or per_link is called
|
||||
* @param per_device: op called for each JESD204 **device** during a transition
|
||||
* @param per_link op called for each JESD204 **link** individually during a transition
|
||||
* // FIXME: maybe pass 'struct jesd204_sysref' for post_state_sysref, to make this configurable? we'll see later
|
||||
* // FIXME: for now, the device should also be a top-level device, in case of multi-chip setups
|
||||
* @param post_state_sysref: true if a SYSREF should be issued after the state change
|
||||
*/
|
||||
struct jesd204_state_op {
|
||||
enum jesd204_state_op_mode mode;
|
||||
jesd204_dev_cb per_device;
|
||||
jesd204_link_cb per_link;
|
||||
bool post_state_sysref;
|
||||
};
|
||||
|
||||
enum jesd204_dev_op {
|
||||
JESD204_OP_DEVICE_INIT,
|
||||
JESD204_OP_LINK_INIT,
|
||||
JESD204_OP_LINK_SUPPORTED,
|
||||
JESD204_OP_LINK_PRE_SETUP,
|
||||
JESD204_OP_CLK_SYNC_STAGE1,
|
||||
JESD204_OP_CLK_SYNC_STAGE2,
|
||||
JESD204_OP_CLK_SYNC_STAGE3,
|
||||
JESD204_OP_LINK_SETUP,
|
||||
JESD204_OP_OPT_SETUP_STAGE1,
|
||||
JESD204_OP_OPT_SETUP_STAGE2,
|
||||
JESD204_OP_OPT_SETUP_STAGE3,
|
||||
JESD204_OP_OPT_SETUP_STAGE4,
|
||||
JESD204_OP_OPT_SETUP_STAGE5,
|
||||
JESD204_OP_CLOCKS_ENABLE,
|
||||
JESD204_OP_LINK_ENABLE,
|
||||
JESD204_OP_LINK_RUNNING,
|
||||
JESD204_OP_OPT_POST_RUNNING_STAGE,
|
||||
|
||||
__JESD204_MAX_OPS,
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct jesd204_dev_data
|
||||
* @brief JESD204 device initialization data
|
||||
* @param sysref_cb: SYSREF callback, if this device/driver supports it
|
||||
* @param sizeof_priv: amount of data to allocate for private information
|
||||
* @param max_num_links: maximum number of JESD204 links this device can support
|
||||
* @param num_retries: number of retries in case of error (only for top-level device)
|
||||
* @param state_ops: ops for each state transition of type @struct jesd204_state_op
|
||||
*/
|
||||
struct jesd204_dev_data {
|
||||
jesd204_sysref_cb sysref_cb;
|
||||
size_t sizeof_priv;
|
||||
unsigned int max_num_links;
|
||||
unsigned int num_retries;
|
||||
struct jesd204_state_op state_ops[__JESD204_MAX_OPS];
|
||||
};
|
||||
|
||||
/* no-OS specific */
|
||||
#define JESD204_MAX_TOPOLOGY_LINKS 16
|
||||
|
||||
/* no-OS specific */
|
||||
struct jesd204_topology_dev {
|
||||
struct jesd204_dev *jdev;
|
||||
bool is_top_device;
|
||||
bool is_sysref_provider;
|
||||
unsigned int link_ids[JESD204_MAX_TOPOLOGY_LINKS];
|
||||
unsigned int links_number;
|
||||
};
|
||||
|
||||
/* no-OS specific */
|
||||
struct jesd204_topology {
|
||||
struct jesd204_dev_top *dev_top;
|
||||
struct jesd204_topology_dev *devs;
|
||||
unsigned int devs_number;
|
||||
};
|
||||
|
||||
/* no-OS specific */
|
||||
int jesd204_dev_register(struct jesd204_dev **jdev,
|
||||
const struct jesd204_dev_data *dev_data);
|
||||
|
||||
/* no-OS specific */
|
||||
int jesd204_dev_unregister(struct jesd204_dev *jdev);
|
||||
|
||||
/* no-OS specific */
|
||||
int jesd204_topology_init(struct jesd204_topology **topology,
|
||||
struct jesd204_topology_dev *devs,
|
||||
unsigned int devs_number);
|
||||
|
||||
/* no-OS specific */
|
||||
int jesd204_topology_remove(struct jesd204_topology *topology);
|
||||
|
||||
/* no-OS specific */
|
||||
int jesd204_fsm_start(struct jesd204_topology *topology, unsigned int link_idx);
|
||||
|
||||
/* no-OS specific */
|
||||
int jesd204_fsm_stop(struct jesd204_topology *topology, unsigned int link_idx);
|
||||
|
||||
void *jesd204_dev_priv(struct jesd204_dev *jdev);
|
||||
|
||||
int jesd204_link_get_lmfc_lemc_rate(struct jesd204_link *lnk,
|
||||
unsigned long *rate_hz);
|
||||
|
||||
int jesd204_link_get_rate_khz(struct jesd204_link *lnk,
|
||||
unsigned long *lane_rate_khz);
|
||||
|
||||
int jesd204_link_get_device_clock(struct jesd204_link *lnk,
|
||||
unsigned long *device_clock);
|
||||
|
||||
int jesd204_sysref_async(struct jesd204_dev *jdev);
|
||||
|
||||
int jesd204_sysref_async_force(struct jesd204_dev *jdev);
|
||||
|
||||
bool jesd204_dev_is_top(struct jesd204_dev *jdev);
|
||||
|
||||
void jesd204_copy_link_params(struct jesd204_link *dst,
|
||||
const struct jesd204_link *src);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,906 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file : main.c
|
||||
* @brief : Main program body
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "main.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
#include "si5351.h"
|
||||
#include "parameters.h"
|
||||
#include "adf4382.h"
|
||||
#include "adar1000.h"
|
||||
#include "hardware_config.h"
|
||||
#include "no_os_delay.h"
|
||||
#include "no_os_alloc.h"
|
||||
#include "no_os_print_log.h"
|
||||
#include "no_os_error.h"
|
||||
#include "no_os_units.h"
|
||||
#include "no_os_dma.h"
|
||||
#include "no_os_spi.h"
|
||||
#include "no_os_uart.h"
|
||||
#include "no_os_util.h"
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PTD */
|
||||
#define debug_uart 1
|
||||
#define BUFFER_SIZE 16 //ADAR
|
||||
#define Delay_scan 1 //Delay between each TX,RX scan// 1 corresponds to 15.6 ns// check delay_15ns() function
|
||||
#define Delay_scan_rx 1 //Delay between each TX,RX scan// 1 corresponds to 15.6 ns// check delay_15ns() function
|
||||
|
||||
Si5351 si5351;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////ADF4382//////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct no_os_uart_init_param adf4382_uart_ip = {
|
||||
.device_id = UART_DEVICE_ID,
|
||||
.irq_id = UART_IRQ_ID,
|
||||
.asynchronous_rx = true,
|
||||
.baud_rate = UART_BAUDRATE,
|
||||
.size = NO_OS_UART_CS_8,
|
||||
.parity = NO_OS_UART_PAR_NO,
|
||||
.stop = NO_OS_UART_STOP_1_BIT,
|
||||
.platform_ops = UART_OPS,
|
||||
.extra = UART_EXTRA,
|
||||
};
|
||||
|
||||
|
||||
struct no_os_spi_init_param adf4382_spi_ip = {
|
||||
.device_id = SPI_DEVICE_ID,
|
||||
.max_speed_hz = 4000000,
|
||||
.chip_select = SPI_CS,
|
||||
.mode = NO_OS_SPI_MODE_0,
|
||||
.bit_order = NO_OS_SPI_BIT_ORDER_MSB_FIRST,
|
||||
.platform_ops = SPI_OPS,
|
||||
.extra = SPI_EXTRA,
|
||||
};
|
||||
|
||||
|
||||
struct adf4382_init_param adf4382_ip = {
|
||||
.spi_init = &adf4382_spi_ip,
|
||||
.spi_3wire_en = false,
|
||||
.cmos_3v3 = false,
|
||||
.ref_freq_hz = 100000000,
|
||||
.freq = 10500000000ULL,
|
||||
.ref_doubler_en = 1,
|
||||
.ref_div = 1,
|
||||
.cp_i = 15,
|
||||
.bleed_word = 4903,
|
||||
.ld_count = 10,
|
||||
.id = ID_ADF4382A,
|
||||
};
|
||||
|
||||
struct adf4382_dev *adf4382_device = NULL; // Pointer to device
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////ADAR1000//////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
uint8_t txBuffer[BUFFER_SIZE] = {0xA1, 0xB2, 0xC3, 0xD4}; // Example data
|
||||
uint8_t rxBuffer1[BUFFER_SIZE] = {0}; // Receive buffer
|
||||
uint8_t rxBuffer2[BUFFER_SIZE] = {0}; // Receive buffer
|
||||
uint8_t rxBuffer3[BUFFER_SIZE] = {0}; // Receive buffer
|
||||
uint8_t rxBuffer4[BUFFER_SIZE] = {0}; // Receive buffer
|
||||
|
||||
uint32_t SpiTransferFunction(uint8_t *p_txData, uint8_t *p_rxData, uint32_t size) {
|
||||
HAL_GPIO_WritePin(GPIO_ADAR, CS_ADAR_1, GPIO_PIN_RESET);
|
||||
HAL_GPIO_WritePin(GPIO_ADAR, CS_ADAR_2, GPIO_PIN_RESET);
|
||||
HAL_GPIO_WritePin(GPIO_ADAR, CS_ADAR_3, GPIO_PIN_RESET);
|
||||
HAL_GPIO_WritePin(GPIO_ADAR, CS_ADAR_4, GPIO_PIN_RESET);
|
||||
HAL_StatusTypeDef status = HAL_SPI_TransmitReceive(&hspi1, p_txData, p_rxData, size, HAL_MAX_DELAY);
|
||||
HAL_GPIO_WritePin(GPIO_ADAR, CS_ADAR_1, GPIO_PIN_SET);
|
||||
HAL_GPIO_WritePin(GPIO_ADAR, CS_ADAR_2, GPIO_PIN_SET);
|
||||
HAL_GPIO_WritePin(GPIO_ADAR, CS_ADAR_3, GPIO_PIN_SET);
|
||||
HAL_GPIO_WritePin(GPIO_ADAR, CS_ADAR_4, GPIO_PIN_SET);
|
||||
return (status == HAL_OK) ? 0 : 1; // Return 0 on success, 1 on failure
|
||||
}
|
||||
|
||||
/// Generic ADAR device that contains a hardware address, SPI transfer function
|
||||
/// and a pointer to a buffer to receive data into.
|
||||
|
||||
// Define the ADAR1000 device instance
|
||||
const AdarDevice ADAR1 = {
|
||||
.dev_addr = 0x00, // Example hardware address
|
||||
.Transfer = SpiTransferFunction, // Assign SPI function pointer
|
||||
.p_rx_buffer = rxBuffer1 // Assign receive buffer
|
||||
};
|
||||
const AdarDevice ADAR2 = {
|
||||
.dev_addr = 0x01, // Example hardware address
|
||||
.Transfer = SpiTransferFunction, // Assign SPI function pointer
|
||||
.p_rx_buffer = rxBuffer2 // Assign receive buffer
|
||||
};
|
||||
const AdarDevice ADAR3 = {
|
||||
.dev_addr = 0x10, // Example hardware address
|
||||
.Transfer = SpiTransferFunction, // Assign SPI function pointer
|
||||
.p_rx_buffer = rxBuffer3 // Assign receive buffer
|
||||
};
|
||||
const AdarDevice ADAR4 = {
|
||||
.dev_addr = 0x11, // Example hardware address
|
||||
.Transfer = SpiTransferFunction, // Assign SPI function pointer
|
||||
.p_rx_buffer = rxBuffer4 // Assign receive buffer
|
||||
};
|
||||
|
||||
AdarBiasCurrents ADAR_BC ={ //bias current
|
||||
.rx_lna = 8, ///< nominal: 8, low power: 5
|
||||
.rx_vm = 5, ///< nominal: 5, low power: 2
|
||||
.rx_vga = 10, ///< nominal: 10, low power: 3
|
||||
.tx_vm = 5, ///< nominal: 5, low power: 2
|
||||
.tx_vga = 5, ///< nominal: 5, low power: 5
|
||||
.tx_drv = 6 ///< nominal: 6, low power: 3
|
||||
};
|
||||
/* USER CODE END PTD */
|
||||
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PD */
|
||||
|
||||
/* USER CODE END PD */
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN PM */
|
||||
|
||||
/* USER CODE END PM */
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
I2C_HandleTypeDef hi2c1;
|
||||
|
||||
SPI_HandleTypeDef hspi1;
|
||||
|
||||
TIM_HandleTypeDef htim1;
|
||||
|
||||
UART_HandleTypeDef huart2;
|
||||
|
||||
/* USER CODE BEGIN PV */
|
||||
|
||||
/* USER CODE END PV */
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
void SystemClock_Config(void);
|
||||
static void MX_GPIO_Init(void);
|
||||
static void MX_I2C1_Init(void);
|
||||
static void MX_SPI1_Init(void);
|
||||
static void MX_TIM1_Init(void);
|
||||
static void MX_USART2_UART_Init(void);
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
void delay_15ns(volatile long unsigned int ns){
|
||||
__HAL_TIM_SET_COUNTER(&htim1,0); // set the counter value a
|
||||
while (__HAL_TIM_GET_COUNTER(&htim1) < ns); // //Clock TIMx -> AHB/APB1 is set to 64MHz/presc+1 presc = 0
|
||||
//delay_15ns(1) would perform a delay of 15.6ns
|
||||
}
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
/* Private user code ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* USER CODE END 0 */
|
||||
|
||||
/**
|
||||
* @brief The application entry point.
|
||||
* @retval int
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
/* USER CODE BEGIN 1 */
|
||||
|
||||
/* USER CODE END 1 */
|
||||
|
||||
/* MCU Configuration--------------------------------------------------------*/
|
||||
|
||||
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
|
||||
HAL_Init();
|
||||
|
||||
/* USER CODE BEGIN Init */
|
||||
|
||||
/* USER CODE END Init */
|
||||
|
||||
/* Configure the system clock */
|
||||
SystemClock_Config();
|
||||
|
||||
/* USER CODE BEGIN SysInit */
|
||||
|
||||
/* USER CODE END SysInit */
|
||||
|
||||
/* Initialize all configured peripherals */
|
||||
MX_GPIO_Init();
|
||||
MX_I2C1_Init();
|
||||
MX_SPI1_Init();
|
||||
MX_TIM1_Init();
|
||||
MX_USART2_UART_Init();
|
||||
/* USER CODE BEGIN 2 */
|
||||
|
||||
HAL_TIM_Base_Start(&htim1);
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////Votage Enable////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//3.3V to ADAR should be set before -5V
|
||||
HAL_GPIO_WritePin(GPIO_VR, EN_32, GPIO_PIN_SET);//active high
|
||||
HAL_GPIO_WritePin(GPIO_VR, EN_42, GPIO_PIN_SET);//active High
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////SI5351///////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);
|
||||
HAL_GPIO_WritePin(GPIO_si5351, SI5351_CLK_EN, GPIO_PIN_RESET);//active low
|
||||
HAL_GPIO_WritePin(GPIO_si5351, SI5351_SS_EN, GPIO_PIN_SET);//active High (Spread Spectrum)
|
||||
//each unity on set_freq(unityULL, SI5351_CLK4) represents 0.01Hz
|
||||
si5351.set_freq(10000000000ULL, SI5351_CLK4);//set FPGA main clock to 100MHz
|
||||
si5351.set_freq(10000000000ULL, SI5351_CLK6);//ADF4382 clock
|
||||
si5351.update_status();
|
||||
HAL_Delay(500);
|
||||
if(debug_uart)
|
||||
{ //When the synthesizers are locked and the Si5351 is working correctly, you'll see an output similar to this one (the REVID may be different):
|
||||
//SYS_INIT: 0 LOL_A: 0 LOL_B: 0 LOS: 0 REVID: 3
|
||||
char buffer[10];
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)"PLLA: " , strlen("PLLA: ") , 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)buffer, sprintf(buffer, "%llu", si5351.plla_freq/100), 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)" PLLB: " , strlen(" PLLB: ") , 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)buffer, sprintf(buffer, "%llu", si5351.pllb_freq/100), 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)" SYS_INIT: " , strlen(" SYS_INIT: ") , 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)buffer, sprintf(buffer, "%u", si5351.dev_status.SYS_INIT), 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)" LOL_A: " , strlen(" LOL_A: ") , 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)buffer, sprintf(buffer, "%u", si5351.dev_status.LOL_A), 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)" LOL_B: " , strlen(" LOL_B ") , 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)buffer, sprintf(buffer, "%u", si5351.dev_status.LOL_B), 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)" LOS: " , strlen(" LOS: ") , 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)buffer, sprintf(buffer, "%u", si5351.dev_status.LOS), 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)" REVID: " , strlen(" REVID: ") , 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)buffer, sprintf(buffer, "%u", si5351.dev_status.REVID), 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)"\r\n" , strlen("\r\n" ) , 10);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////ADF4382//////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int status = adf4382_init(&adf4382_device ,&adf4382_ip);
|
||||
if (status != 0) {
|
||||
// Handle initialization error
|
||||
}
|
||||
|
||||
|
||||
status = adf4382_set_freq(adf4382_device);
|
||||
if (status != 0) {
|
||||
// Handle frequency setting error
|
||||
}
|
||||
|
||||
adf4382_set_en_chan(adf4382_device, 0, true);
|
||||
adf4382_set_en_chan(adf4382_device, 1, true);
|
||||
HAL_GPIO_WritePin(GPIO_ADF, ADF_CE, GPIO_PIN_SET);//active High
|
||||
|
||||
//HAL_GPIO_WritePin(GPIO_ADF, ADF_DELSTR, GPIO_PIN_SET);
|
||||
//HAL_GPIO_WritePin(GPIO_ADF, ADF_DELADJ, GPIO_PIN_SET);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////LTC5552 Mixers///////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HAL_GPIO_WritePin(GPIO_DIG, DIG_2, GPIO_PIN_SET); //Enable RX Mixer
|
||||
HAL_GPIO_WritePin(GPIO_DIG, DIG_3, GPIO_PIN_SET); //Enable TX Mixer
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////ADAR1000/////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//phase_step = 0 => phase = 0°
|
||||
//phase_step = 127 => phase = 360°
|
||||
//steering angle (rad)= arcsin(phase_dif/Pi)
|
||||
|
||||
uint8_t matrix1[22][16];
|
||||
uint8_t vector_0[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
uint8_t matrix2[22][16];
|
||||
for(int j=0; j<15;j++){
|
||||
for(int i=0; i<21;i++){
|
||||
matrix1[i][j]=(2*(i+1)*(15-j))%127;
|
||||
matrix2[i][j]=matrix1[i][15-j];
|
||||
i++;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
Adar_AdcInit(&ADAR1, BROADCAST_OFF);//init. ADC
|
||||
Adar_AdcInit(&ADAR2, BROADCAST_OFF);//init. ADC
|
||||
Adar_AdcInit(&ADAR3, BROADCAST_OFF);//init. ADC
|
||||
Adar_AdcInit(&ADAR4, BROADCAST_OFF);//init. ADC
|
||||
uint8_t Temp1 = Adar_AdcRead(&ADAR1,BROADCAST_OFF);//Read ADC from single ADAR
|
||||
uint8_t Temp2 = Adar_AdcRead(&ADAR2,BROADCAST_OFF);
|
||||
uint8_t Temp3 = Adar_AdcRead(&ADAR3,BROADCAST_OFF);
|
||||
uint8_t Temp4 = Adar_AdcRead(&ADAR4,BROADCAST_OFF);
|
||||
|
||||
if(debug_uart){
|
||||
char buffer[10];
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)"Temp1: " , strlen("Temp1: ") , 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)buffer, sprintf(buffer, "%u", Temp1), 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)" Temp2: " , strlen(" Temp2: ") , 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)buffer, sprintf(buffer, "%u", Temp2), 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)" Temp3: " , strlen(" Temp3: ") , 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)buffer, sprintf(buffer, "%u", Temp3), 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)" Temp4: " , strlen(" Temp4: ") , 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)buffer, sprintf(buffer, "%u", Temp4), 10);
|
||||
HAL_UART_Transmit(&huart2, (uint8_t*)"\r\n" , strlen("\r\n" ) , 10);
|
||||
}
|
||||
|
||||
Adar_SetBiasCurrents(&ADAR1,&ADAR_BC,BROADCAST_OFF);
|
||||
Adar_SetBiasCurrents(&ADAR2,&ADAR_BC,BROADCAST_OFF);
|
||||
Adar_SetBiasCurrents(&ADAR3,&ADAR_BC,BROADCAST_OFF);
|
||||
Adar_SetBiasCurrents(&ADAR4,&ADAR_BC,BROADCAST_OFF);
|
||||
|
||||
uint8_t bias_on_voltage [5] = {0x39, 0x39, 0x39, 0x39, 0x00};//V_PA = -1.1V; V_LNA = 0V
|
||||
uint8_t bias_off_voltage [5] = {0x85, 0x85, 0x85, 0x85, 0x68};//V_PA = -2.5V; V_LNA = -2V
|
||||
|
||||
HAL_GPIO_WritePin(GPIO_DIG, DIG_0, GPIO_PIN_RESET);//reset TR pin on FPGA for RX mode
|
||||
Adar_SetBiasVoltages(&ADAR1, bias_on_voltage, bias_off_voltage);
|
||||
Adar_SetBiasVoltages(&ADAR2, bias_on_voltage, bias_off_voltage);
|
||||
Adar_SetBiasVoltages(&ADAR3, bias_on_voltage, bias_off_voltage);
|
||||
Adar_SetBiasVoltages(&ADAR4, bias_on_voltage, bias_off_voltage);
|
||||
|
||||
Adar_SetRxVgaGain(&ADAR1, 1, 16, BROADCAST_OFF);//16dB is the max
|
||||
Adar_SetRxVgaGain(&ADAR1, 2, 16, BROADCAST_OFF);
|
||||
Adar_SetRxVgaGain(&ADAR1, 3, 16, BROADCAST_OFF);
|
||||
Adar_SetRxVgaGain(&ADAR1, 4, 16, BROADCAST_OFF);
|
||||
|
||||
Adar_SetRxVgaGain(&ADAR2, 1, 16, BROADCAST_OFF);//16dB is the max
|
||||
Adar_SetRxVgaGain(&ADAR2, 2, 16, BROADCAST_OFF);
|
||||
Adar_SetRxVgaGain(&ADAR2, 3, 16, BROADCAST_OFF);
|
||||
Adar_SetRxVgaGain(&ADAR2, 4, 16, BROADCAST_OFF);
|
||||
|
||||
Adar_SetRxVgaGain(&ADAR3, 1, 16, BROADCAST_OFF);//16dB is the max
|
||||
Adar_SetRxVgaGain(&ADAR3, 2, 16, BROADCAST_OFF);
|
||||
Adar_SetRxVgaGain(&ADAR3, 3, 16, BROADCAST_OFF);
|
||||
Adar_SetRxVgaGain(&ADAR3, 4, 16, BROADCAST_OFF);
|
||||
|
||||
Adar_SetRxVgaGain(&ADAR4, 1, 16, BROADCAST_OFF);//16dB is the max
|
||||
Adar_SetRxVgaGain(&ADAR4, 2, 16, BROADCAST_OFF);
|
||||
Adar_SetRxVgaGain(&ADAR4, 3, 16, BROADCAST_OFF);
|
||||
Adar_SetRxVgaGain(&ADAR4, 4, 16, BROADCAST_OFF);
|
||||
|
||||
Adar_SetTxBias(&ADAR1, BROADCAST_OFF);//set to nominal...check adar1000.c
|
||||
Adar_SetTxBias(&ADAR2, BROADCAST_OFF);
|
||||
Adar_SetTxBias(&ADAR3, BROADCAST_OFF);
|
||||
Adar_SetTxBias(&ADAR4, BROADCAST_OFF);
|
||||
|
||||
Adar_SetTxVgaGain(&ADAR1, 1, 0x7D, BROADCAST_OFF);//0xFF = max
|
||||
Adar_SetTxVgaGain(&ADAR1, 2, 0x7D, BROADCAST_OFF);
|
||||
Adar_SetTxVgaGain(&ADAR1, 3, 0x7D, BROADCAST_OFF);
|
||||
Adar_SetTxVgaGain(&ADAR1, 4, 0x7D, BROADCAST_OFF);
|
||||
|
||||
Adar_SetTxVgaGain(&ADAR2, 1, 0x7D, BROADCAST_OFF);//0xFF = max
|
||||
Adar_SetTxVgaGain(&ADAR2, 2, 0x7D, BROADCAST_OFF);
|
||||
Adar_SetTxVgaGain(&ADAR2, 3, 0x7D, BROADCAST_OFF);
|
||||
Adar_SetTxVgaGain(&ADAR2, 4, 0x7D, BROADCAST_OFF);
|
||||
|
||||
Adar_SetTxVgaGain(&ADAR3, 1, 0x7D, BROADCAST_OFF);//0xFF = max
|
||||
Adar_SetTxVgaGain(&ADAR3, 2, 0x7D, BROADCAST_OFF);
|
||||
Adar_SetTxVgaGain(&ADAR3, 3, 0x7D, BROADCAST_OFF);
|
||||
Adar_SetTxVgaGain(&ADAR3, 4, 0x7D, BROADCAST_OFF);
|
||||
|
||||
Adar_SetTxVgaGain(&ADAR4, 1, 0x7D, BROADCAST_OFF);//0xFF = max
|
||||
Adar_SetTxVgaGain(&ADAR4, 2, 0x7D, BROADCAST_OFF);
|
||||
Adar_SetTxVgaGain(&ADAR4, 3, 0x7D, BROADCAST_OFF);
|
||||
Adar_SetTxVgaGain(&ADAR4, 4, 0x7D, BROADCAST_OFF);
|
||||
/* USER CODE END 2 */
|
||||
|
||||
/* Infinite loop */
|
||||
/* USER CODE BEGIN WHILE */
|
||||
while (1)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////ADAR1000/////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//phase_step = 0 => phase = 0°
|
||||
//phase_step = 127 => phase = 360°
|
||||
//steering angle (rad)= arcsin(phase_dif/Pi)
|
||||
HAL_GPIO_WritePin(GPIO_DIG, DIG_1, GPIO_PIN_SET); // Send to FPGA_FT2232HQ start frame from ADC Matrix
|
||||
HAL_Delay(1);
|
||||
HAL_GPIO_WritePin(GPIO_DIG, DIG_1, GPIO_PIN_RESET); // Send to FPGA_FT2232HQ start frame from ADC Matrix
|
||||
|
||||
for(int i = 0; i<21; i++){
|
||||
|
||||
Adar_SetTxPhase(&ADAR1,1 ,matrix1[i][0] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR1,2 ,matrix1[i][1] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR1,3 ,matrix1[i][2] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR1,4 ,matrix1[i][3] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetTxPhase(&ADAR2,1 ,matrix1[i][4] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR2,2 ,matrix1[i][5] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR2,3 ,matrix1[i][6] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR2,4 ,matrix1[i][7] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetTxPhase(&ADAR3,1 ,matrix1[i][8] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR3,2 ,matrix1[i][9] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR3,3 ,matrix1[i][10] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR3,4 ,matrix1[i][11] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetTxPhase(&ADAR4,1 ,matrix1[i][12] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR4,2 ,matrix1[i][13] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR4,3 ,matrix1[i][14] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR4,4 ,matrix1[i][15] , BROADCAST_OFF);
|
||||
HAL_GPIO_WritePin(GPIO_DIG, DIG_0, GPIO_PIN_SET);//set TR pin on FPGA for TX mode
|
||||
HAL_GPIO_TogglePin(GPIO_LED, LED_1);
|
||||
delay_15ns(Delay_scan);
|
||||
|
||||
Adar_SetRxPhase(&ADAR1,1 ,matrix1[i][0] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR1,2 ,matrix1[i][1] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR1,3 ,matrix1[i][2] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR1,4 ,matrix1[i][3] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetRxPhase(&ADAR2,1 ,matrix1[i][4] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR2,2 ,matrix1[i][5] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR2,3 ,matrix1[i][6] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR2,4 ,matrix1[i][7] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetRxPhase(&ADAR3,1 ,matrix1[i][8] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR3,2 ,matrix1[i][9] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR3,3 ,matrix1[i][10] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR3,4 ,matrix1[i][11] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetRxPhase(&ADAR4,1 ,matrix1[i][12] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR4,2 ,matrix1[i][13] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR4,3 ,matrix1[i][14] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR4,4 ,matrix1[i][15] , BROADCAST_OFF);
|
||||
HAL_GPIO_WritePin(GPIO_DIG, DIG_0, GPIO_PIN_RESET);//reset TR pin on FPGA for RX mode
|
||||
HAL_GPIO_TogglePin(GPIO_LED, LED_2);
|
||||
delay_15ns(Delay_scan_rx);
|
||||
}
|
||||
for(int i = 0; i<15; i++){
|
||||
|
||||
Adar_SetTxPhase(&ADAR1,1 ,vector_0[0] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR1,2 ,vector_0[1] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR1,3 ,vector_0[2] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR1,4 ,vector_0[3] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetTxPhase(&ADAR2,1 ,vector_0[4] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR2,2 ,vector_0[5] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR2,3 ,vector_0[6] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR2,4 ,vector_0[7] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetTxPhase(&ADAR3,1 ,vector_0[8] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR3,2 ,vector_0[9] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR3,3 ,vector_0[10] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR3,4 ,vector_0[11] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetTxPhase(&ADAR4,1 ,vector_0[12] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR4,2 ,vector_0[13] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR4,3 ,vector_0[14] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR4,4 ,vector_0[15] , BROADCAST_OFF);
|
||||
HAL_GPIO_WritePin(GPIO_DIG, DIG_0, GPIO_PIN_SET);//set TR pin on FPGA for TX mode
|
||||
HAL_GPIO_TogglePin(GPIO_LED, LED_1);
|
||||
delay_15ns(Delay_scan);
|
||||
|
||||
Adar_SetRxPhase(&ADAR1,1 ,vector_0[0] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR1,2 ,vector_0[1] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR1,3 ,vector_0[2] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR1,4 ,vector_0[3] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetRxPhase(&ADAR2,1 ,vector_0[4] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR2,2 ,vector_0[5] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR2,3 ,vector_0[6] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR2,4 ,vector_0[7] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetRxPhase(&ADAR3,1 ,vector_0[8] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR3,2 ,vector_0[9] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR3,3 ,vector_0[10] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR3,4 ,vector_0[11] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetRxPhase(&ADAR4,1 ,vector_0[12] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR4,2 ,vector_0[13] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR4,3 ,vector_0[14] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR4,4 ,vector_0[15] , BROADCAST_OFF);
|
||||
HAL_GPIO_WritePin(GPIO_DIG, DIG_0, GPIO_PIN_RESET);//reset TR pin on FPGA for RX mode
|
||||
HAL_GPIO_TogglePin(GPIO_LED, LED_2);
|
||||
delay_15ns(Delay_scan_rx);
|
||||
}
|
||||
|
||||
for(int i = 0; i<21; i++){
|
||||
|
||||
Adar_SetTxPhase(&ADAR1,1 ,matrix2[i][0] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR1,2 ,matrix2[i][1] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR1,3 ,matrix2[i][2] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR1,4 ,matrix2[i][3] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetTxPhase(&ADAR2,1 ,matrix2[i][4] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR2,2 ,matrix2[i][5] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR2,3 ,matrix2[i][6] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR2,4 ,matrix2[i][7] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetTxPhase(&ADAR3,1 ,matrix2[i][8] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR3,2 ,matrix2[i][9] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR3,3 ,matrix2[i][10] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR3,4 ,matrix2[i][11] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetTxPhase(&ADAR4,1 ,matrix2[i][12] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR4,2 ,matrix2[i][13] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR4,3 ,matrix2[i][14] , BROADCAST_OFF);
|
||||
Adar_SetTxPhase(&ADAR4,4 ,matrix2[i][15] , BROADCAST_OFF);
|
||||
HAL_GPIO_WritePin(GPIO_DIG, DIG_0, GPIO_PIN_SET);//set TR pin on FPGA for TX mode
|
||||
HAL_GPIO_TogglePin(GPIO_LED, LED_1);
|
||||
delay_15ns(Delay_scan);
|
||||
|
||||
Adar_SetRxPhase(&ADAR1,1 ,matrix2[i][0] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR1,2 ,matrix2[i][1] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR1,3 ,matrix2[i][2] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR1,4 ,matrix2[i][3] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetRxPhase(&ADAR2,1 ,matrix2[i][4] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR2,2 ,matrix2[i][5] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR2,3 ,matrix2[i][6] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR2,4 ,matrix2[i][7] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetRxPhase(&ADAR3,1 ,matrix2[i][8] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR3,2 ,matrix2[i][9] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR3,3 ,matrix2[i][10] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR3,4 ,matrix2[i][11] , BROADCAST_OFF);
|
||||
|
||||
Adar_SetRxPhase(&ADAR4,1 ,matrix2[i][12] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR4,2 ,matrix2[i][13] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR4,3 ,matrix2[i][14] , BROADCAST_OFF);
|
||||
Adar_SetRxPhase(&ADAR4,4 ,matrix2[i][15] , BROADCAST_OFF);
|
||||
HAL_GPIO_WritePin(GPIO_DIG, DIG_0, GPIO_PIN_RESET);//reset TR pin on FPGA for RX mode
|
||||
HAL_GPIO_TogglePin(GPIO_LED, LED_2);
|
||||
delay_15ns(Delay_scan_rx);
|
||||
}
|
||||
//Send commands to the auxilliary board to set motor position and get GPS data
|
||||
|
||||
/* USER CODE END WHILE */
|
||||
|
||||
/* USER CODE BEGIN 3 */
|
||||
}
|
||||
/* USER CODE END 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief System Clock Configuration
|
||||
* @retval None
|
||||
*/
|
||||
void SystemClock_Config(void)
|
||||
{
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
||||
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
||||
|
||||
/** Configure LSE Drive Capability
|
||||
*/
|
||||
HAL_PWR_EnableBkUpAccess();
|
||||
|
||||
/** Configure the main internal regulator output voltage
|
||||
*/
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
|
||||
|
||||
/** Initializes the RCC Oscillators according to the specified parameters
|
||||
* in the RCC_OscInitTypeDef structure.
|
||||
*/
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
||||
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
||||
RCC_OscInitStruct.PLL.PLLM = 4;
|
||||
RCC_OscInitStruct.PLL.PLLN = 64;
|
||||
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
|
||||
RCC_OscInitStruct.PLL.PLLQ = 2;
|
||||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/** Initializes the CPU, AHB and APB buses clocks
|
||||
*/
|
||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|
||||
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
|
||||
|
||||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2C1 Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_I2C1_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN I2C1_Init 0 */
|
||||
|
||||
/* USER CODE END I2C1_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN I2C1_Init 1 */
|
||||
|
||||
/* USER CODE END I2C1_Init 1 */
|
||||
hi2c1.Instance = I2C1;
|
||||
hi2c1.Init.Timing = 0x00707CBB;
|
||||
hi2c1.Init.OwnAddress1 = 0;
|
||||
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
|
||||
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
|
||||
hi2c1.Init.OwnAddress2 = 0;
|
||||
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
|
||||
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
|
||||
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
|
||||
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/** Configure Analogue filter
|
||||
*/
|
||||
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/** Configure Digital filter
|
||||
*/
|
||||
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN I2C1_Init 2 */
|
||||
|
||||
/* USER CODE END I2C1_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI1 Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_SPI1_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN SPI1_Init 0 */
|
||||
|
||||
/* USER CODE END SPI1_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN SPI1_Init 1 */
|
||||
|
||||
/* USER CODE END SPI1_Init 1 */
|
||||
/* SPI1 parameter configuration*/
|
||||
hspi1.Instance = SPI1;
|
||||
hspi1.Init.Mode = SPI_MODE_MASTER;
|
||||
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
|
||||
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
|
||||
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
|
||||
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
|
||||
hspi1.Init.NSS = SPI_NSS_SOFT;
|
||||
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
|
||||
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
|
||||
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
|
||||
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
|
||||
hspi1.Init.CRCPolynomial = 7;
|
||||
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
|
||||
hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
|
||||
if (HAL_SPI_Init(&hspi1) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN SPI1_Init 2 */
|
||||
|
||||
/* USER CODE END SPI1_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TIM1 Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_TIM1_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN TIM1_Init 0 */
|
||||
|
||||
/* USER CODE END TIM1_Init 0 */
|
||||
|
||||
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
|
||||
TIM_MasterConfigTypeDef sMasterConfig = {0};
|
||||
|
||||
/* USER CODE BEGIN TIM1_Init 1 */
|
||||
|
||||
/* USER CODE END TIM1_Init 1 */
|
||||
htim1.Instance = TIM1;
|
||||
htim1.Init.Prescaler = 0;
|
||||
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
htim1.Init.Period = 65535;
|
||||
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||
htim1.Init.RepetitionCounter = 0;
|
||||
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
|
||||
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
|
||||
sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
|
||||
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
|
||||
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN TIM1_Init 2 */
|
||||
|
||||
/* USER CODE END TIM1_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USART2 Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_USART2_UART_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN USART2_Init 0 */
|
||||
|
||||
/* USER CODE END USART2_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN USART2_Init 1 */
|
||||
|
||||
/* USER CODE END USART2_Init 1 */
|
||||
huart2.Instance = USART2;
|
||||
huart2.Init.BaudRate = 115200;
|
||||
huart2.Init.WordLength = UART_WORDLENGTH_8B;
|
||||
huart2.Init.StopBits = UART_STOPBITS_1;
|
||||
huart2.Init.Parity = UART_PARITY_NONE;
|
||||
huart2.Init.Mode = UART_MODE_TX_RX;
|
||||
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
|
||||
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
|
||||
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
|
||||
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
|
||||
if (HAL_UART_Init(&huart2) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN USART2_Init 2 */
|
||||
|
||||
/* USER CODE END USART2_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GPIO Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_GPIO_Init(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
/* USER CODE BEGIN MX_GPIO_Init_1 */
|
||||
/* USER CODE END MX_GPIO_Init_1 */
|
||||
|
||||
/* GPIO Ports Clock Enable */
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOH_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||||
|
||||
/*Configure GPIO pin Output Level */
|
||||
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET);
|
||||
|
||||
/*Configure GPIO pin Output Level */
|
||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_4|GPIO_PIN_5, GPIO_PIN_RESET);
|
||||
|
||||
/*Configure GPIO pin Output Level */
|
||||
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13
|
||||
|GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET);
|
||||
|
||||
/*Configure GPIO pin Output Level */
|
||||
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11, GPIO_PIN_RESET);
|
||||
|
||||
/*Configure GPIO pins : PC4 PC5 PC6 PC7 */
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pins : PC0 PC1 PC2 PC3 */
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pins : PB14 PB15 PB4 PB5 */
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_4|GPIO_PIN_5;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pins : PD10 PD11 PD12 PD13
|
||||
PD0 PD1 PD2 PD3 */
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13
|
||||
|GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
|
||||
|
||||
/*Configure GPIO pins : PA8 PA9 PA10 PA11 */
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
/* USER CODE BEGIN MX_GPIO_Init_2 */
|
||||
/* USER CODE END MX_GPIO_Init_2 */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 4 */
|
||||
|
||||
/* USER CODE END 4 */
|
||||
|
||||
/**
|
||||
* @brief This function is executed in case of error occurrence.
|
||||
* @retval None
|
||||
*/
|
||||
void Error_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN Error_Handler_Debug */
|
||||
/* User can add his own implementation to report the HAL error return state */
|
||||
__disable_irq();
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
/* USER CODE END Error_Handler_Debug */
|
||||
}
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
/**
|
||||
* @brief Reports the name of the source file and the source line number
|
||||
* where the assert_param error has occurred.
|
||||
* @param file: pointer to the source file name
|
||||
* @param line: assert_param error line source number
|
||||
* @retval None
|
||||
*/
|
||||
void assert_failed(uint8_t *file, uint32_t line)
|
||||
{
|
||||
/* USER CODE BEGIN 6 */
|
||||
/* User can add his own implementation to report the file name and line number,
|
||||
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
|
||||
/* USER CODE END 6 */
|
||||
}
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
@@ -0,0 +1,70 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file : main.h
|
||||
* @brief : Header for main.c file.
|
||||
* This file contains the common defines of the application.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2025 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __MAIN_H
|
||||
#define __MAIN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f7xx_hal.h"
|
||||
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN ET */
|
||||
|
||||
/* USER CODE END ET */
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EC */
|
||||
|
||||
/* USER CODE END EC */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EM */
|
||||
|
||||
/* USER CODE END EM */
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void Error_Handler(void);
|
||||
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
|
||||
/* USER CODE BEGIN Private defines */
|
||||
|
||||
/* USER CODE END Private defines */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MAIN_H */
|
||||
@@ -0,0 +1,70 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_ain.h
|
||||
* @author PMallick (Pratyush.Mallick@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright (c) 2021-22 Analog Devices, Inc.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef NO_OS_AIN_H
|
||||
#define NO_OS_AIN_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/**
|
||||
* @struct ain_init_param
|
||||
* @brief Structure holding parameters for analog input initialization
|
||||
*/
|
||||
struct no_os_ain_init_param {
|
||||
/* Analog input reference voltage */
|
||||
float vref;
|
||||
/* Analog extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct ain_desc
|
||||
* @brief Structure holding analog input descriptor
|
||||
*/
|
||||
struct no_os_ain_desc {
|
||||
/* Analog input reference voltage */
|
||||
float vref;
|
||||
/* Analog extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/* Read analog input voltage */
|
||||
int32_t no_os_ain_get_voltage(struct no_os_ain_desc *desc, float *value);
|
||||
|
||||
/* Initialize the analog input peripheral*/
|
||||
int32_t no_os_ain_init(struct no_os_ain_desc **desc,
|
||||
const struct no_os_ain_init_param *param);
|
||||
|
||||
/* Free the resources allocated by no_os_ain_init() */
|
||||
int32_t no_os_ain_remove(struct no_os_ain_desc *desc);
|
||||
|
||||
#endif // end of NO_OS_AIN_H
|
||||
@@ -0,0 +1,67 @@
|
||||
/*******************************************************************************
|
||||
* @file util/no_os_alloc.c
|
||||
* @brief Implementation of no-OS memory allocation functions.
|
||||
* @author GMois (george.mois@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2023(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "no_os_alloc.h"
|
||||
|
||||
/**
|
||||
* @brief Allocate memory and return a pointer to it.
|
||||
* @param size - Size of the memory block, in bytes.
|
||||
* @return Pointer to the allocated memory, or NULL if the request fails.
|
||||
*/
|
||||
__attribute__((weak)) void *no_os_malloc(size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocate memory and return a pointer to it, set memory to 0.
|
||||
* @param nitems - Number of elements to be allocated.
|
||||
* @param size - Size of elements.
|
||||
* @return Pointer to the allocated memory, or NULL if the request fails.
|
||||
*/
|
||||
__attribute__((weak)) void *no_os_calloc(size_t nitems, size_t size)
|
||||
{
|
||||
return calloc(nitems, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deallocate memory previously allocated by a call to no_os_calloc
|
||||
* or no_os_malloc.
|
||||
* @param ptr - Pointer to a memory block previously allocated by a call
|
||||
* to no_os_calloc or no_os_malloc.
|
||||
* @return None.
|
||||
*/
|
||||
__attribute__((weak)) void no_os_free(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*******************************************************************************
|
||||
* @file no_os_alloc.h
|
||||
* @brief Header file of memory allocator.
|
||||
* @author GMois (george.mois@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2023(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_ALLOC_H_
|
||||
#define _NO_OS_ALLOC_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Allocate memory and return a pointer to it */
|
||||
void *no_os_malloc(size_t size);
|
||||
|
||||
/* Allocate memory and return a pointer to it, set memory to 0 */
|
||||
void *no_os_calloc(size_t nitems, size_t size);
|
||||
|
||||
/* Deallocate memory previously allocated by a call to no_os_calloc or
|
||||
* no_os_malloc */
|
||||
void no_os_free(void *ptr);
|
||||
|
||||
#endif // _NO_OS_ALLOC_H_
|
||||
@@ -0,0 +1,78 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_aout.h
|
||||
* @author PMallick (Pratyush.Mallick@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright (c) 2021-22 Analog Devices, Inc.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef NO_OS_AOUT_H
|
||||
#define NO_OS_AOUT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/**
|
||||
* @struct aout_init_param
|
||||
* @brief Structure holding the parameters for analog output initialization
|
||||
*/
|
||||
struct no_os_aout_init_param {
|
||||
/* Min output range of DAC in volts */
|
||||
float aout_min_v;
|
||||
/* Max output range of DAC in volts */
|
||||
float aout_max_v;
|
||||
/* Analog output reference voltage */
|
||||
float vref;
|
||||
/* Analog extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct aout_desc
|
||||
* @brief Structure holding analog output descriptor
|
||||
*/
|
||||
struct no_os_aout_desc {
|
||||
/* Min output value of DAC in volts */
|
||||
float aout_min_v;
|
||||
/* Max output value of DAC in volts */
|
||||
float aout_max_v;
|
||||
/* Analog output reference voltage */
|
||||
float vref;
|
||||
/* Analog extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/* Write analog output voltage */
|
||||
int32_t no_os_aout_set_voltage(struct no_os_aout_desc *desc, float value);
|
||||
|
||||
/* Initialize the analog output peripheral */
|
||||
int32_t no_so_aout_init(struct no_os_aout_desc **desc,
|
||||
const struct no_os_aout_init_param *param);
|
||||
|
||||
/* Free the resources allocated by no_os_aout_init() */
|
||||
int32_t no_os_aout_remove(struct no_os_aout_desc *desc);
|
||||
|
||||
#endif // end of NO_OS_AOUT_H
|
||||
@@ -0,0 +1,45 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_axi_io.h
|
||||
* @brief Header file of AXI IO.
|
||||
* @author Antoniu Miclaus (antoniu.miclaus@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _NO_OS_AXI_IO_H_
|
||||
#define _NO_OS_AXI_IO_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* AXI IO Read data */
|
||||
int32_t no_os_axi_io_read(uint32_t base, uint32_t offset, uint32_t *data);
|
||||
|
||||
/* AXI IO Write data */
|
||||
int32_t no_os_axi_io_write(uint32_t base, uint32_t offset, uint32_t data);
|
||||
|
||||
#endif // _NO_OS_AXI_IO_H_
|
||||
@@ -0,0 +1,390 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_circular_buffer.c
|
||||
* @brief Circular buffer implementation
|
||||
* @author Mihail Chindris (mihail.chindris@analog.com)
|
||||
********************************************************************************
|
||||
* @copyright
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "no_os_circular_buffer.h"
|
||||
#include "no_os_error.h"
|
||||
#include "no_os_util.h"
|
||||
#include "no_os_alloc.h"
|
||||
|
||||
int32_t no_os_cb_cfg(struct no_os_circular_buffer *desc, int8_t *buff,
|
||||
uint32_t size)
|
||||
{
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
memset(desc, 0, sizeof(*desc));
|
||||
desc->size = size;
|
||||
desc->buff = buff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create circular buffer structure.
|
||||
*
|
||||
* @note Circular buffer implementation is thread safe for one write
|
||||
* and one reader.
|
||||
* If multiple writer or multiple readers access the circular buffer then
|
||||
* function that updates the structure should be called inside a critical
|
||||
* critical section.
|
||||
*
|
||||
* @param desc - Where to store the circular buffer reference
|
||||
* @param buff_size - Buffer size
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
*/
|
||||
int32_t no_os_cb_init(struct no_os_circular_buffer **desc, uint32_t buff_size)
|
||||
{
|
||||
struct no_os_circular_buffer *ldesc;
|
||||
|
||||
if (!desc || !buff_size)
|
||||
return -EINVAL;
|
||||
|
||||
ldesc = (struct no_os_circular_buffer*)no_os_calloc(1, sizeof(*ldesc));
|
||||
if (!ldesc)
|
||||
return -ENOMEM;
|
||||
|
||||
*desc = ldesc;
|
||||
|
||||
ldesc->size = buff_size;
|
||||
ldesc->buff = no_os_calloc(1, buff_size);
|
||||
if (!ldesc->buff) {
|
||||
no_os_free(ldesc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated for the circular buffer structure.
|
||||
* @param desc - Circular buffer reference
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
*/
|
||||
int32_t no_os_cb_remove(struct no_os_circular_buffer *desc)
|
||||
{
|
||||
if (!desc)
|
||||
return -1;
|
||||
|
||||
if (desc->buff)
|
||||
no_os_free(desc->buff);
|
||||
no_os_free(desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the number of elements in the buffer.
|
||||
* @param desc - Circular buffer reference
|
||||
* @param size - Where to store size of data available to read
|
||||
* @return
|
||||
* - 0 - No errors
|
||||
* - -EINVAL - Wrong parameters used
|
||||
* - -NO_OS_EOVERRUN - A buffer overrun occurred
|
||||
*/
|
||||
int32_t no_os_cb_size(struct no_os_circular_buffer *desc, uint32_t *size)
|
||||
{
|
||||
uint32_t nb_spins;
|
||||
|
||||
if (!desc || !size)
|
||||
return -EINVAL;
|
||||
|
||||
if (desc->write.spin_count > desc->read.spin_count)
|
||||
nb_spins = desc->write.spin_count - desc->read.spin_count;
|
||||
else
|
||||
/* Integer overflow on desc->write.spin_count */
|
||||
nb_spins = UINT32_MAX - desc->read.spin_count +
|
||||
desc->write.spin_count + 1;
|
||||
|
||||
if (nb_spins > 0)
|
||||
*size = desc->size + desc->write.idx - desc->read.idx;
|
||||
else
|
||||
*size = desc->write.idx - desc->read.idx;
|
||||
|
||||
if (*size > desc->size) {
|
||||
*size = desc->size;
|
||||
return -NO_OS_EOVERRUN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Functionality described at no_os_cb_prepare_async_write/read having the is_read
|
||||
* parameter to specifiy if it is a read or write operation.
|
||||
*/
|
||||
static int32_t no_os_cb_prepare_async_operation(struct no_os_circular_buffer
|
||||
*desc,
|
||||
uint32_t requested_size,
|
||||
void **buff,
|
||||
uint32_t *raw_size_available,
|
||||
bool is_read)
|
||||
{
|
||||
struct no_os_cb_ptr *ptr;
|
||||
uint32_t available_size;
|
||||
int32_t ret;
|
||||
|
||||
if (!desc || !buff || !raw_size_available)
|
||||
return -EINVAL;
|
||||
|
||||
ret = 0;
|
||||
/* Select if read or write index will be updated */
|
||||
ptr = is_read ? &desc->read : &desc->write;
|
||||
|
||||
/* Only one transaction type possible at a single time */
|
||||
if (ptr->async_started)
|
||||
return -EBUSY;
|
||||
|
||||
if (is_read) {
|
||||
ret = no_os_cb_size(desc, &available_size);
|
||||
if (ret == -NO_OS_EOVERRUN) {
|
||||
/* Update read index */
|
||||
desc->read.spin_count = desc->write.spin_count - 1;
|
||||
#ifndef IIO_IGNORE_BUFF_OVERRUN_ERR
|
||||
desc->read.idx = desc->write.idx;
|
||||
#endif
|
||||
}
|
||||
if (!available_size)
|
||||
/* No data to read */
|
||||
return 0;
|
||||
|
||||
/* We can only read available data */
|
||||
requested_size = no_os_min(requested_size, available_size);
|
||||
if (!requested_size)
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/* Size to end of buffer */
|
||||
ptr->async_size = no_os_min(requested_size, desc->size - ptr->idx);
|
||||
|
||||
*raw_size_available = ptr->async_size;
|
||||
|
||||
/* Convert index to address in the buffer */
|
||||
*buff = (void *)(desc->buff + ptr->idx);
|
||||
|
||||
ptr->async_started = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Functionality described at no_os_cb_end_async_write/read having the is_read
|
||||
* parameter to specifiy if it is a read or write operation.
|
||||
*/
|
||||
static int32_t no_os_cb_end_async_operation(struct no_os_circular_buffer *desc,
|
||||
bool is_read)
|
||||
{
|
||||
struct no_os_cb_ptr *ptr;
|
||||
uint32_t new_val;
|
||||
|
||||
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
/* Select if read or write index will be updated */
|
||||
ptr = is_read ? &desc->read : &desc->write;
|
||||
|
||||
/* Transaction not started */
|
||||
if (!ptr->async_started)
|
||||
return -1;
|
||||
|
||||
/* Update pointer value */
|
||||
new_val = ptr->idx + ptr->async_size;
|
||||
if (new_val >= desc->size) {
|
||||
ptr->spin_count++;
|
||||
new_val %= desc->size;
|
||||
}
|
||||
ptr->idx = new_val;
|
||||
ptr->async_size = 0;
|
||||
ptr->async_started = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Functionality described at cb_write/read having the is_read
|
||||
* parameter to specifiy if it is a read or write operation.
|
||||
*/
|
||||
static int32_t no_os_cb_operation(struct no_os_circular_buffer *desc,
|
||||
void *data, uint32_t size,
|
||||
bool is_read)
|
||||
{
|
||||
uint8_t *buff;
|
||||
uint32_t available_size = 0;
|
||||
int32_t ret;
|
||||
uint32_t i;
|
||||
bool sticky_overrun;
|
||||
|
||||
if (!desc || !data || !size)
|
||||
return -EINVAL;
|
||||
|
||||
sticky_overrun = 0;
|
||||
i = 0;
|
||||
while (i < size) {
|
||||
do {
|
||||
ret = no_os_cb_prepare_async_operation(desc, size - i,
|
||||
(void **)&buff,
|
||||
&available_size,
|
||||
is_read);
|
||||
} while (ret == -EBUSY || ret == -EAGAIN);
|
||||
if (ret == -NO_OS_EOVERRUN)
|
||||
sticky_overrun = true;
|
||||
|
||||
/* If no data is available return error */
|
||||
if (!available_size)
|
||||
return -1;
|
||||
|
||||
if (is_read)
|
||||
memcpy((uint8_t *)data + i, buff, available_size);
|
||||
else
|
||||
memcpy(buff, (uint8_t *)data + i, available_size);
|
||||
|
||||
no_os_cb_end_async_operation(desc, is_read);
|
||||
|
||||
i += available_size;
|
||||
}
|
||||
|
||||
if (sticky_overrun)
|
||||
return -NO_OS_EOVERRUN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepare asynchronous write.
|
||||
*
|
||||
* Get the inside raw buffer to be used in DMA transactions.
|
||||
*
|
||||
* @param desc - Circular buffer reference
|
||||
* @param size_to_write - Number of bytes needed to write to the buffer.
|
||||
* @param write_buff - Address where to store the buffer where to write to.
|
||||
* @param size_avilable - no_os_min(size_to_write, size until end of allocated buffer)
|
||||
* @return
|
||||
* - 0 - No errors
|
||||
* - -EINVAL - Wrong parameters used
|
||||
* - -EBUSY - Asynchronous transaction already started
|
||||
*/
|
||||
int32_t no_os_cb_prepare_async_write(struct no_os_circular_buffer *desc,
|
||||
uint32_t size_to_write,
|
||||
void **write_buff,
|
||||
uint32_t *size_avilable)
|
||||
{
|
||||
return no_os_cb_prepare_async_operation(desc, size_to_write, write_buff,
|
||||
size_avilable, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepare asynchronous read.
|
||||
*
|
||||
* Get the inside raw buffer to be used in DMA transactions.
|
||||
*
|
||||
* @param desc - Circular buffer reference
|
||||
* @param size_to_read - Number of bytes needed to write to the buffer.
|
||||
* @param read_buff - Address where to store the buffer where data will be read.
|
||||
* @param size_avilable - no_os_min(size_to_read, size until end of allocated buffer)
|
||||
* @return
|
||||
* - 0 - No errors
|
||||
* - -EAGAIN - No data available at this moment
|
||||
* - -EINVAL - Wrong parameters used
|
||||
* - -EBUSY - Asynchronous transaction already started
|
||||
* - -NO_OS_EOVERRUN - An overrun occurred and some data have been overwritten
|
||||
*/
|
||||
int32_t no_os_cb_prepare_async_read(struct no_os_circular_buffer *desc,
|
||||
uint32_t size_to_read,
|
||||
void **read_buff,
|
||||
uint32_t *size_avilable)
|
||||
{
|
||||
return no_os_cb_prepare_async_operation(desc, size_to_read, read_buff,
|
||||
size_avilable, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* \defgroup end_async_group End Ashyncronous functions
|
||||
* @brief End asynchronous transaction.
|
||||
*
|
||||
* @param desc - Circular buffer reference
|
||||
* @return
|
||||
* - 0 - No errors
|
||||
* - -1 - Asynchronous transaction not started
|
||||
* - -EINVAL - Wrong parameters used
|
||||
* @{
|
||||
*/
|
||||
int32_t no_os_cb_end_async_write(struct no_os_circular_buffer *desc)
|
||||
{
|
||||
return no_os_cb_end_async_operation(desc, 0);
|
||||
}
|
||||
|
||||
int32_t no_os_cb_end_async_read(struct no_os_circular_buffer *desc)
|
||||
{
|
||||
|
||||
return no_os_cb_end_async_operation(desc, 1);
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Write data to the buffer (Blocking).
|
||||
* @param desc - Circular buffer reference
|
||||
* @param data - Buffer from where data is copied to the circular buffer
|
||||
* @param size - Size to write
|
||||
* @return
|
||||
* - 0 - No errors
|
||||
* - -EINVAL - Wrong parameters used
|
||||
*/
|
||||
int32_t no_os_cb_write(struct no_os_circular_buffer *desc, const void *data,
|
||||
uint32_t size)
|
||||
{
|
||||
return no_os_cb_operation(desc, (void *)data, size, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read data from the buffer (Blocking).
|
||||
* @param desc - Circular buffer reference
|
||||
* @param data - Buffer where to data is copied from the circular buffer
|
||||
* @param size - Size to read
|
||||
* @return
|
||||
* - 0 - No errors
|
||||
* - -EINVAL - Wrong parameters used
|
||||
* - -NO_OS_EOVERRUN - An overrun occurred and some data have been overwritten
|
||||
*/
|
||||
int32_t no_os_cb_read(struct no_os_circular_buffer *desc, void *data,
|
||||
uint32_t size)
|
||||
{
|
||||
return no_os_cb_operation(desc, data, size, 1);
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_circular_buffer.h
|
||||
* @brief Circular buffer library header
|
||||
* @author Mihail Chindris (mihail.chindris@analog.com)
|
||||
********************************************************************************
|
||||
* @copyright
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _NO_OS_CIRCULAR_BUFFER_H_
|
||||
#define _NO_OS_CIRCULAR_BUFFER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @struct no_os_cb_ptr
|
||||
* @brief Circular buffer pointer
|
||||
*/
|
||||
struct no_os_cb_ptr {
|
||||
/** Index of data in the buffer */
|
||||
uint32_t idx;
|
||||
/** Counts the number of times idx exceeds the liniar buffer */
|
||||
uint32_t spin_count;
|
||||
/** Set if async transaction is active */
|
||||
bool async_started;
|
||||
/** Number of bytes to update after an async transaction is finished */
|
||||
uint32_t async_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_circular_buffer
|
||||
* @brief Circular buffer descriptor
|
||||
*/
|
||||
struct no_os_circular_buffer {
|
||||
/** Size of the buffer in bytes */
|
||||
uint32_t size;
|
||||
/** Address of the buffer */
|
||||
int8_t *buff;
|
||||
/** Write pointer */
|
||||
struct no_os_cb_ptr write;
|
||||
/** Read pointer */
|
||||
struct no_os_cb_ptr read;
|
||||
};
|
||||
|
||||
int32_t no_os_cb_init(struct no_os_circular_buffer **desc, uint32_t size);
|
||||
/* Configure cb structure with given parameters without memory allocation */
|
||||
int32_t no_os_cb_cfg(struct no_os_circular_buffer *desc, int8_t *buf,
|
||||
uint32_t size);
|
||||
int32_t no_os_cb_remove(struct no_os_circular_buffer *desc);
|
||||
int32_t no_os_cb_size(struct no_os_circular_buffer *desc, uint32_t *size);
|
||||
|
||||
int32_t no_os_cb_write(struct no_os_circular_buffer *desc, const void *data,
|
||||
uint32_t nb_elements);
|
||||
int32_t no_os_cb_read(struct no_os_circular_buffer *desc, void *data,
|
||||
uint32_t nb_elements);
|
||||
|
||||
int32_t no_os_cb_prepare_async_write(struct no_os_circular_buffer *desc,
|
||||
uint32_t raw_size_to_write,
|
||||
void **write_buff,
|
||||
uint32_t *raw_size_avilable);
|
||||
int32_t no_os_cb_end_async_write(struct no_os_circular_buffer *desc);
|
||||
|
||||
int32_t no_os_cb_prepare_async_read(struct no_os_circular_buffer *desc,
|
||||
uint32_t raw_size_to_read,
|
||||
void **read_buff,
|
||||
uint32_t *raw_size_avilable);
|
||||
int32_t no_os_cb_end_async_read(struct no_os_circular_buffer *desc);
|
||||
|
||||
#endif //_NO_OS_CIRCULAR_BUFFER_H_
|
||||
@@ -0,0 +1,193 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_clk.c
|
||||
* @brief Implementation of Clock Driver.
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/***************************** Include Files **********************************/
|
||||
/******************************************************************************/
|
||||
#include "no_os_alloc.h"
|
||||
#include "no_os_error.h"
|
||||
#include "no_os_clk.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/************************** Functions Implementation **************************/
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* Initialize clock.
|
||||
* @param desc - CLK descriptor.
|
||||
* @param param - The structure that contains CLK parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_clk_init(struct no_os_clk_desc **desc,
|
||||
const struct no_os_clk_init_param *param)
|
||||
{
|
||||
struct no_os_clk_desc *clk;
|
||||
int ret;
|
||||
|
||||
if (!desc || !param || !param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
clk = (struct no_os_clk_desc *)no_os_calloc(1, sizeof(*clk));
|
||||
if (!clk)
|
||||
return -ENOMEM;
|
||||
|
||||
clk->name = param->name;
|
||||
clk->hw_ch_num = param->hw_ch_num;
|
||||
clk->dev_desc = param->dev_desc;
|
||||
clk->platform_ops = param->platform_ops;
|
||||
|
||||
if (param->platform_ops->init) {
|
||||
ret = param->platform_ops->init(desc, param);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
*desc = clk;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
no_os_free(clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by no_os_clk_init().
|
||||
* @param desc - The clock descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_clk_remove(struct no_os_clk_desc *desc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (desc->platform_ops->remove) {
|
||||
ret = desc->platform_ops->remove(desc);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
no_os_free(desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the clock.
|
||||
* @param clk - The clock descriptor.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t no_os_clk_enable(struct no_os_clk_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->clk_enable)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->clk_enable(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the clock.
|
||||
* @param clk - The clock descriptor.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t no_os_clk_disable(struct no_os_clk_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->clk_disable)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->clk_disable(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current frequency of the clock.
|
||||
* @param clk - The clock descriptor.
|
||||
* @param rate - The current frequency.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t no_os_clk_recalc_rate(struct no_os_clk_desc *desc,
|
||||
uint64_t *rate)
|
||||
{
|
||||
if (!desc || !desc->platform_ops || !rate)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->clk_recalc_rate)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->clk_recalc_rate(desc, rate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Round the desired frequency to a rate that the clock can actually output.
|
||||
* @param clk - The clock descriptor.
|
||||
* @param rate - The desired frequency.
|
||||
* @param rounded_rate - The rounded frequency.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t no_os_clk_round_rate(struct no_os_clk_desc *desc,
|
||||
uint64_t rate,
|
||||
uint64_t *rounded_rate)
|
||||
{
|
||||
if (!desc || !desc->platform_ops || !rounded_rate)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->clk_round_rate)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->clk_round_rate(desc, rate, rounded_rate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the frequency of the clock.
|
||||
* @param clk - The clock descriptor.
|
||||
* @param rate - The desired frequency.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t no_os_clk_set_rate(struct no_os_clk_desc *desc,
|
||||
uint64_t rate)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->clk_set_rate)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->clk_set_rate(desc, rate);
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_clk.h
|
||||
* @brief Header file of Clock Driver.
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_CLK_H_
|
||||
#define _NO_OS_CLK_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct no_os_clk_init_param {
|
||||
/** Device name */
|
||||
const char *name;
|
||||
/** Channel number */
|
||||
uint8_t hw_ch_num;
|
||||
/** CLK function pointers */
|
||||
const struct no_os_clk_platform_ops *platform_ops;
|
||||
/** CLK hardware device descriptor */
|
||||
void *dev_desc;
|
||||
};
|
||||
|
||||
struct no_os_clk_hw {
|
||||
void *dev;
|
||||
int32_t (*dev_clk_enable)();
|
||||
int32_t (*dev_clk_disable)();
|
||||
int32_t (*dev_clk_recalc_rate)();
|
||||
int32_t (*dev_clk_set_rate)();
|
||||
int32_t (*dev_clk_round_rate)();
|
||||
};
|
||||
|
||||
struct no_os_clk {
|
||||
struct no_os_clk_hw *hw;
|
||||
uint32_t hw_ch_num;
|
||||
const char *name;
|
||||
const struct no_os_clk_desc *clk_desc;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_clk_desc
|
||||
* @brief Structure holding CLK descriptor.
|
||||
*/
|
||||
typedef struct no_os_clk_desc {
|
||||
/** Device name */
|
||||
const char *name;
|
||||
/** Channel number */
|
||||
uint8_t hw_ch_num;
|
||||
/** CLK function pointers */
|
||||
const struct no_os_clk_platform_ops *platform_ops;
|
||||
/** CLK hardware device descriptor */
|
||||
void *dev_desc;
|
||||
} no_os_clk_desc;
|
||||
|
||||
/**
|
||||
* @struct no_os_clk_platform_ops
|
||||
* @brief Structure holding CLK function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_clk_platform_ops {
|
||||
/** Initialize CLK function pointer. */
|
||||
int (*init)(struct no_os_clk_desc **, const struct no_os_clk_init_param *);
|
||||
/** Start CLK function pointer. */
|
||||
int (*clk_enable)(struct no_os_clk_desc *);
|
||||
/** Stop CLK function pointer. */
|
||||
int (*clk_disable)(struct no_os_clk_desc *);
|
||||
/** Get the current frequency of CLK function pointer. */
|
||||
int (*clk_recalc_rate)(struct no_os_clk_desc *, uint64_t *);
|
||||
/* Round the desired frequency to a rate that CLK can actually output. */
|
||||
int (*clk_round_rate)(struct no_os_clk_desc *, uint64_t, uint64_t *);
|
||||
/* Change CLK frequency function pointer. */
|
||||
int (*clk_set_rate)(struct no_os_clk_desc *, uint64_t);
|
||||
/** CLK remove function pointer */
|
||||
int (*remove)(struct no_os_clk_desc *);
|
||||
};
|
||||
|
||||
/* Initialize CLK ops. */
|
||||
int32_t no_os_clk_init(struct no_os_clk_desc **desc,
|
||||
const struct no_os_clk_init_param *param);
|
||||
|
||||
/* Free the resources allocated by no_os_clk_init(). */
|
||||
int32_t no_os_clk_remove(struct no_os_clk_desc *desc);
|
||||
|
||||
/* Start the clock. */
|
||||
int32_t no_os_clk_enable(struct no_os_clk_desc *desc);
|
||||
|
||||
/* Stop the clock. */
|
||||
int32_t no_os_clk_disable(struct no_os_clk_desc *desc);
|
||||
|
||||
/* Get the current frequency of the clock. */
|
||||
int32_t no_os_clk_recalc_rate(struct no_os_clk_desc *desc,
|
||||
uint64_t *rate);
|
||||
|
||||
/* Round the desired frequency to a rate that the clock can actually output. */
|
||||
int32_t no_os_clk_round_rate(struct no_os_clk_desc *desc,
|
||||
uint64_t rate,
|
||||
uint64_t *rounded_rate);
|
||||
|
||||
/* Change the frequency of the clock. */
|
||||
int32_t no_os_clk_set_rate(struct no_os_clk_desc *desc,
|
||||
uint64_t rate);
|
||||
|
||||
#endif // _NO_OS_CLK_H_
|
||||
@@ -0,0 +1,40 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_crc.h
|
||||
* @brief Generic header file for all CRC computation algorithms.
|
||||
* @author Darius Berghe (darius.berghe@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_CRC_H_
|
||||
#define _NO_OS_CRC_H_
|
||||
|
||||
#include "no_os_crc8.h"
|
||||
#include "no_os_crc16.h"
|
||||
#include "no_os_crc24.h"
|
||||
|
||||
#endif // _NO_OS_CRC_H_
|
||||
@@ -0,0 +1,97 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_crc16.c
|
||||
* @brief Source file of CRC-16 computation.
|
||||
* @author Darius Berghe (darius.berghe@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#include "no_os_crc16.h"
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Creates the CRC-16 lookup table for a given polynomial.
|
||||
*
|
||||
* @param table - Pointer to a CRC-16 lookup table to write to.
|
||||
* @param polynomial - Msb-first representation of desired polynomial.
|
||||
*
|
||||
* Polynomials in CRC algorithms are typically represented as shown below.
|
||||
*
|
||||
* poly = x^16 + x^14 + x^13 + x^12 + x^10 + x^8 + x^6 + x^4 + x^3 +
|
||||
* x^1 + 1
|
||||
*
|
||||
* Using msb-first direction, x^15 maps to the msb.
|
||||
*
|
||||
* msb first: poly = (1)0111010101011011 = 0x755B
|
||||
* ^
|
||||
*
|
||||
* @return None.
|
||||
*******************************************************************************/
|
||||
void no_os_crc16_populate_msb(uint16_t * table, const uint16_t polynomial)
|
||||
{
|
||||
if (!table)
|
||||
return;
|
||||
|
||||
for (int16_t n = 0; n < NO_OS_CRC16_TABLE_SIZE; n++) {
|
||||
uint16_t currByte = (uint16_t)(n << 8);
|
||||
for (uint8_t bit = 0; bit < 8; bit++) {
|
||||
if ((currByte & 0x8000) != 0) {
|
||||
currByte <<= 1;
|
||||
currByte ^= polynomial;
|
||||
} else {
|
||||
currByte <<= 1;
|
||||
}
|
||||
}
|
||||
table[n] = currByte;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Computes the CRC-16 over a buffer of data.
|
||||
*
|
||||
* @param table - Pointer to a CRC-16 lookup table for the desired polynomial.
|
||||
* @param pdata - Pointer to data buffer.
|
||||
* @param nbytes - Number of bytes to compute the CRC-16 over.
|
||||
* @param crc - Initial value for the CRC-16 computation. Can be used to
|
||||
* cascade calls to this function by providing a previous
|
||||
* output of this function as the crc parameter.
|
||||
*
|
||||
* @return crc - Computed CRC-16 value.
|
||||
*******************************************************************************/
|
||||
uint16_t no_os_crc16(const uint16_t * table, const uint8_t *pdata,
|
||||
size_t nbytes,
|
||||
uint16_t crc)
|
||||
{
|
||||
unsigned int idx;
|
||||
|
||||
while (nbytes--) {
|
||||
idx = ((crc >> 8) ^ *pdata) & 0xff;
|
||||
crc = (table[idx] ^ (crc << 8)) & 0xffff;
|
||||
pdata++;
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_crc16.h
|
||||
* @brief Header file of CRC-16 computation.
|
||||
* @author Darius Berghe (darius.berghe@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_CRC16_H_
|
||||
#define _NO_OS_CRC16_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define NO_OS_CRC16_TABLE_SIZE 256
|
||||
|
||||
#define NO_OS_DECLARE_CRC16_TABLE(_table) \
|
||||
static uint16_t _table[NO_OS_CRC16_TABLE_SIZE]
|
||||
|
||||
void no_os_crc16_populate_msb(uint16_t * table, const uint16_t polynomial);
|
||||
uint16_t no_os_crc16(const uint16_t * table, const uint8_t *pdata,
|
||||
size_t nbytes,
|
||||
uint16_t crc);
|
||||
|
||||
#endif // _NO_OS_CRC16_H_
|
||||
@@ -0,0 +1,98 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_crc24.c
|
||||
* @brief Source file of CRC-24 computation.
|
||||
* @author Antoniu Miclaus (antoniu.miclaus@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2021(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#include "no_os_crc24.h"
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Creates the CRC-24 lookup table for a given polynomial.
|
||||
*
|
||||
* @param table - Pointer to a CRC-24 lookup table to write to.
|
||||
* @param polynomial - msb-first representation of desired polynomial.
|
||||
*
|
||||
* Polynomials in CRC algorithms are typically represented as shown below.
|
||||
*
|
||||
* poly = x^24 + x^22 + x^20 + x^19 + x^18 + x^16 + x^14 + x^13 + x^11 +
|
||||
* x^10 + x^8 + x^7 + x^6 + x^3 + x^1 + 1
|
||||
*
|
||||
* Using msb-first direction, x^24 maps to the msb.
|
||||
*
|
||||
* msb first: poly = (1)010111010110110111001011 = 5D6DCB
|
||||
* ^
|
||||
*
|
||||
* @return None.
|
||||
*******************************************************************************/
|
||||
void no_os_crc24_populate_msb(uint32_t * table, const uint32_t polynomial)
|
||||
{
|
||||
if (!table)
|
||||
return;
|
||||
|
||||
for (int16_t n = 0; n < NO_OS_CRC24_TABLE_SIZE; n++) {
|
||||
uint32_t currByte = (uint32_t)(n << 16);
|
||||
for (uint8_t bit = 0; bit < 8; bit++) {
|
||||
if ((currByte & 0x800000) != 0) {
|
||||
currByte &= 0x7FFFFF;
|
||||
currByte <<= 1;
|
||||
currByte ^= polynomial;
|
||||
} else {
|
||||
currByte <<= 1;
|
||||
}
|
||||
}
|
||||
table[n] = currByte;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Computes the CRC-24 over a buffer of data.
|
||||
*
|
||||
* @param table - Pointer to a CRC-24 lookup table for the desired polynomial.
|
||||
* @param pdata - Pointer to data buffer.
|
||||
* @param nbytes - Number of bytes to compute the CRC-24 over.
|
||||
* @param crc - Initial value for the CRC-24 computation. Can be used to
|
||||
* cascade calls to this function by providing a previous
|
||||
* output of this function as the crc parameter.
|
||||
*
|
||||
* @return crc - Computed CRC-24 value.
|
||||
*******************************************************************************/
|
||||
uint32_t no_os_crc24(const uint32_t * table, const uint8_t *pdata,
|
||||
size_t nbytes,
|
||||
uint32_t crc)
|
||||
{
|
||||
unsigned int idx;
|
||||
|
||||
while (nbytes--) {
|
||||
idx = ((crc >> 16) ^ *pdata) & 0xff;
|
||||
crc = (table[idx] ^ (crc << 8)) & 0xffffff;
|
||||
pdata++;
|
||||
}
|
||||
|
||||
return (crc & 0xffffff);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_crc24.h
|
||||
* @brief Header file of CRC-24 computation.
|
||||
* @author Antoniu Miclaus (antoniu.miclaus@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2021(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_CRC24_H_
|
||||
#define _NO_OS_CRC24_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define NO_OS_CRC24_TABLE_SIZE 256
|
||||
|
||||
#define NO_OS_DECLARE_CRC24_TABLE(_table) \
|
||||
static uint32_t _table[NO_OS_CRC24_TABLE_SIZE]
|
||||
|
||||
void no_os_crc24_populate_msb(uint32_t * table, const uint32_t polynomial);
|
||||
uint32_t no_os_crc24(const uint32_t * table, const uint8_t *pdata,
|
||||
size_t nbytes,
|
||||
uint32_t crc);
|
||||
|
||||
#endif // _NO_OS_CRC24_H_
|
||||
@@ -0,0 +1,94 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_crc8.c
|
||||
* @brief Source file of CRC-8 computation.
|
||||
* @author Darius Berghe (darius.berghe@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#include "no_os_crc8.h"
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Creates the CRC-8 lookup table for a given polynomial.
|
||||
*
|
||||
* @param table - Pointer to a CRC-8 lookup table to write to.
|
||||
* @param polynomial - msb-first representation of desired polynomial.
|
||||
*
|
||||
* Polynomials in CRC algorithms are typically represented as shown below.
|
||||
*
|
||||
* poly = x^8 + x^2 + x^1 + 1
|
||||
*
|
||||
* Using msb-first direction, x^7 maps to the msb.
|
||||
*
|
||||
* msb first: poly = (1)00000111 = 0x07
|
||||
*
|
||||
* @return None.
|
||||
*******************************************************************************/
|
||||
void no_os_crc8_populate_msb(uint8_t * table, const uint8_t polynomial)
|
||||
{
|
||||
if (!table)
|
||||
return;
|
||||
|
||||
for (int16_t n = 0; n < NO_OS_CRC8_TABLE_SIZE; n++) {
|
||||
uint8_t currByte = (uint8_t)n;
|
||||
for (uint8_t bit = 0; bit < 8; bit++) {
|
||||
if ((currByte & 0x80) != 0) {
|
||||
currByte <<= 1;
|
||||
currByte ^= polynomial;
|
||||
} else {
|
||||
currByte <<= 1;
|
||||
}
|
||||
}
|
||||
table[n] = currByte;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Computes the CRC-8 over a buffer of data.
|
||||
*
|
||||
* @param table - Pointer to a CRC-8 lookup table for the desired polynomial.
|
||||
* @param pdata - Pointer to 8-bit data buffer.
|
||||
* @param nbytes - Number of bytes to compute the CRC-8 over.
|
||||
* @param crc - Initial value for the CRC-8 computation. Can be used to
|
||||
* cascade calls to this function by providing a previous
|
||||
* output of this function as the crc parameter.
|
||||
*
|
||||
* @return crc - Computed CRC-8 value.
|
||||
*******************************************************************************/
|
||||
uint8_t no_os_crc8(const uint8_t * table, const uint8_t *pdata, size_t nbytes,
|
||||
uint8_t crc)
|
||||
{
|
||||
unsigned int idx;
|
||||
|
||||
while (nbytes--) {
|
||||
idx = (crc ^ *pdata);
|
||||
crc = (table[idx]) & 0xff;
|
||||
pdata++;
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_crc8.h
|
||||
* @brief Header file of CRC-8 computation.
|
||||
* @author Darius Berghe (darius.berghe@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_CRC8_H_
|
||||
#define _NO_OS_CRC8_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define NO_OS_CRC8_TABLE_SIZE 256
|
||||
|
||||
#define NO_OS_DECLARE_CRC8_TABLE(_table) \
|
||||
static uint8_t _table[NO_OS_CRC8_TABLE_SIZE]
|
||||
|
||||
void no_os_crc8_populate_msb(uint8_t * table, const uint8_t polynomial);
|
||||
uint8_t no_os_crc8(const uint8_t * table, const uint8_t *pdata, size_t nbytes,
|
||||
uint8_t crc);
|
||||
|
||||
#endif // _NO_OS_CRC8_H_
|
||||
@@ -0,0 +1,56 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_delay.h
|
||||
* @brief Header file of Delay functions
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _NO_OS_DELAY_H_
|
||||
#define _NO_OS_DELAY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @struct no_os_time
|
||||
* @brief Structure holding time data (seconds, microseconds).
|
||||
*/
|
||||
struct no_os_time {
|
||||
unsigned int s, us;
|
||||
};
|
||||
|
||||
/* Generate microseconds delay. */
|
||||
void no_os_udelay(uint32_t usecs);
|
||||
|
||||
/* Generate miliseconds delay. */
|
||||
void no_os_mdelay(uint32_t msecs);
|
||||
|
||||
/* Get current time */
|
||||
struct no_os_time no_os_get_time(void);
|
||||
|
||||
#endif // _NO_OS_DELAY_H_
|
||||
@@ -0,0 +1,449 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_dma.c
|
||||
* @brief Platform independent implementation for the DMA API.
|
||||
* @author Ciprian Regus (ciprian.regus@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2024(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#include <inttypes.h>
|
||||
#include "no_os_dma.h"
|
||||
#include <stdlib.h>
|
||||
#include "no_os_error.h"
|
||||
#include "no_os_mutex.h"
|
||||
#include "no_os_irq.h"
|
||||
#include "no_os_alloc.h"
|
||||
#include "no_os_list.h"
|
||||
|
||||
/**
|
||||
* @brief Default handler for cycling though the channel's list of transfers
|
||||
* @param context - structure which stores the state of the current channel
|
||||
* and DMA controller state.
|
||||
*/
|
||||
static void default_sg_callback(void *context)
|
||||
{
|
||||
struct no_os_dma_default_handler_data *data = context;
|
||||
struct no_os_dma_xfer_desc *next_xfer;
|
||||
struct no_os_dma_xfer_desc *old_xfer;
|
||||
uint32_t list_size;
|
||||
int ret;
|
||||
|
||||
/* Handle the next transfer from the SG list */
|
||||
ret = no_os_list_get_first(data->channel->sg_list, (void **)&old_xfer);
|
||||
if (ret) {
|
||||
/*
|
||||
* This should only happen if the list descriptor is NULL.
|
||||
* The case in which there is no transfer left in the list should
|
||||
* have been handled in the previous interrupt.
|
||||
*/
|
||||
no_os_dma_xfer_abort(data->desc, data->channel);
|
||||
return;
|
||||
}
|
||||
|
||||
no_os_list_read_first(data->channel->sg_list, (void **)&next_xfer);
|
||||
no_os_list_get_size(data->channel->sg_list, &list_size);
|
||||
if (old_xfer->xfer_complete_cb)
|
||||
old_xfer->xfer_complete_cb(old_xfer, next_xfer,
|
||||
old_xfer->xfer_complete_ctx);
|
||||
|
||||
if (!list_size) {
|
||||
no_os_irq_disable(data->desc->irq_ctrl, data->channel->irq_num);
|
||||
data->channel->free = true;
|
||||
return;
|
||||
}
|
||||
|
||||
data->desc->platform_ops->dma_config_xfer(data->channel, next_xfer);
|
||||
|
||||
no_os_dma_xfer_start(data->desc, data->channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the DMA controller.
|
||||
* @param desc - Structure containing the state of the DMA controller
|
||||
* @param param - Initialization parameter for the DMA controller.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int no_os_dma_init(struct no_os_dma_desc **desc,
|
||||
struct no_os_dma_init_param *param)
|
||||
{
|
||||
int ret;
|
||||
uint32_t i, j;
|
||||
void *mutex;
|
||||
|
||||
if (!param || !param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->dma_init)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_init(&mutex);
|
||||
|
||||
no_os_mutex_lock(mutex);
|
||||
ret = param->platform_ops->dma_init(desc, param);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
no_os_mutex_init(&(*desc)->mutex);
|
||||
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
|
||||
for (i = 0; i < param->num_ch; i++) {
|
||||
ret = no_os_list_init(&(*desc)->channels[i].sg_list, NO_OS_LIST_QUEUE, NULL);
|
||||
if (ret)
|
||||
goto list_err;
|
||||
|
||||
no_os_mutex_init(&(*desc)->channels[i].mutex);
|
||||
}
|
||||
|
||||
(*desc)->ref++;
|
||||
no_os_mutex_unlock(mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
list_err:
|
||||
for (j = 0; j < i; j++)
|
||||
no_os_list_remove((*desc)->channels[i].sg_list);
|
||||
|
||||
no_os_dma_remove(*desc);
|
||||
unlock:
|
||||
no_os_mutex_unlock(mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove resources allocated for the DMA controller.
|
||||
* @param desc - Structure containing the state of the DMA controller
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int no_os_dma_remove(struct no_os_dma_desc *desc)
|
||||
{
|
||||
uint32_t i;
|
||||
int ret;
|
||||
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->ref)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < desc->num_ch; i++) {
|
||||
ret = no_os_list_remove(desc->channels->sg_list);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
no_os_mutex_remove(desc->channels[i].mutex);
|
||||
if (desc->irq_ctrl && desc->channels[i].cb_desc.handle) {
|
||||
no_os_irq_unregister_callback(desc->irq_ctrl,
|
||||
desc->channels[i].irq_num,
|
||||
&desc->channels[i].cb_desc);
|
||||
}
|
||||
|
||||
}
|
||||
no_os_mutex_remove(desc->mutex);
|
||||
|
||||
ret = desc->platform_ops->dma_remove(desc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
desc->ref--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a free DMA channel.
|
||||
* @param desc - Structure containing the state of the DMA controller.
|
||||
* @param channel - Reference to the acquired channel.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int no_os_dma_acquire_channel(struct no_os_dma_desc *desc,
|
||||
struct no_os_dma_ch **channel)
|
||||
{
|
||||
uint32_t ch_num;
|
||||
int ret;
|
||||
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->dma_acquire_ch)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_lock(desc->mutex);
|
||||
|
||||
ret = desc->platform_ops->dma_acquire_ch(desc, &ch_num);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
*channel = &desc->channels[ch_num];
|
||||
|
||||
unlock:
|
||||
no_os_mutex_unlock(desc->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free DMA channel.
|
||||
* @param desc - Structure containing the state of the DMA controller.
|
||||
* @param channel - Reference to the currently acquired channel.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int no_os_dma_release_channel(struct no_os_dma_desc *desc,
|
||||
struct no_os_dma_ch *channel)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!desc || !desc->platform_ops || !channel)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->dma_release_ch)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_lock(channel->mutex);
|
||||
ret = desc->platform_ops->dma_release_ch(desc, channel->id);
|
||||
no_os_mutex_unlock(channel->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Acquire a channel and configure the list of transfers.
|
||||
* @param desc - Structure containing the state of the DMA controller
|
||||
* @param xfer - Array of DMA transfers.
|
||||
* @param len - The number of transfers in the xfer list.
|
||||
* @param ch - Previously acquired channel, for which the transfer will be configured.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int no_os_dma_config_xfer(struct no_os_dma_desc *desc,
|
||||
struct no_os_dma_xfer_desc *xfer,
|
||||
uint32_t len, struct no_os_dma_ch *ch)
|
||||
{
|
||||
uint32_t i;
|
||||
int ret;
|
||||
void *discard;
|
||||
struct no_os_callback_desc *sg_callback;
|
||||
|
||||
if (!desc || !xfer || !len || !ch)
|
||||
return -EINVAL;
|
||||
|
||||
no_os_mutex_lock(ch->mutex);
|
||||
|
||||
/*
|
||||
* Add the transfers to the channel's SG list. It's safe to do so, since
|
||||
* there are no ongoing transfers on this channel.
|
||||
*/
|
||||
for (i = 0; i < len; i++)
|
||||
no_os_list_add_last(ch->sg_list, &xfer[i]);
|
||||
|
||||
if (desc->irq_ctrl) {
|
||||
sg_callback = &ch->cb_desc;
|
||||
sg_callback->ctx = &ch->irq_ctx;
|
||||
sg_callback->handle = (void *)ch->id;
|
||||
sg_callback->peripheral = xfer[0].periph;
|
||||
ch->irq_ctx.desc = desc;
|
||||
ch->irq_ctx.channel = ch;
|
||||
|
||||
switch (xfer[0].xfer_type) {
|
||||
case MEM_TO_DEV:
|
||||
case MEM_TO_MEM:
|
||||
sg_callback->event = NO_OS_EVT_DMA_TX_COMPLETE;
|
||||
break;
|
||||
case DEV_TO_MEM:
|
||||
sg_callback->event = NO_OS_EVT_DMA_RX_COMPLETE;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = desc->platform_ops->dma_config_xfer(ch, xfer);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (desc->sg_handler)
|
||||
sg_callback->callback = desc->sg_handler;
|
||||
else
|
||||
sg_callback->callback = default_sg_callback;
|
||||
|
||||
ret = no_os_irq_register_callback(desc->irq_ctrl,
|
||||
ch->irq_num,
|
||||
sg_callback);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
no_os_irq_set_priority(desc->irq_ctrl, ch->irq_num, xfer[0].irq_priority);
|
||||
}
|
||||
|
||||
no_os_mutex_unlock(ch->mutex);
|
||||
return 0;
|
||||
err:
|
||||
for (i = 0; i < len; i++)
|
||||
no_os_list_get_first(ch->sg_list, &discard);
|
||||
no_os_mutex_unlock(ch->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Lock a DMA channel, so it won't be acquired even if it's free.
|
||||
* @param ch - Reference to the DMA channel
|
||||
* @return 0 in case of success, -EINVAL if a NULL channel reference is provided.
|
||||
*/
|
||||
int no_os_dma_chan_lock(struct no_os_dma_ch *ch)
|
||||
{
|
||||
no_os_mutex_lock(ch->mutex);
|
||||
|
||||
if (!ch)
|
||||
return -EINVAL;
|
||||
|
||||
ch->sync_lock = true;
|
||||
|
||||
no_os_mutex_unlock(ch->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unlock a DMA channel, marking it available for acquisition.
|
||||
* @param ch - Reference to the DMA channel
|
||||
* @return 0 in case of success, -EINVAL if a NULL channel reference is provided.
|
||||
*/
|
||||
int no_os_dma_chan_unlock(struct no_os_dma_ch *ch)
|
||||
{
|
||||
no_os_mutex_lock(ch->mutex);
|
||||
|
||||
if (!ch)
|
||||
return -EINVAL;
|
||||
|
||||
ch->sync_lock = false;
|
||||
|
||||
no_os_mutex_unlock(ch->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Acquire a channel and configure the list of transfers.
|
||||
* @param desc - Structure containing the state of the DMA controller
|
||||
* @param ch - Index for the channel we want to start the transfer on.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int no_os_dma_xfer_start(struct no_os_dma_desc *desc, struct no_os_dma_ch *ch)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!desc || !desc->platform_ops || !ch)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->dma_xfer_start)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_lock(ch->mutex);
|
||||
|
||||
if (desc->irq_ctrl)
|
||||
no_os_irq_enable(desc->irq_ctrl, ch->irq_num);
|
||||
|
||||
ret = desc->platform_ops->dma_xfer_start(desc, ch);
|
||||
|
||||
no_os_mutex_unlock(ch->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort the ongoing and any other future transfers scheduled for a channel.
|
||||
* @param desc - Structure containing the state of the DMA controller
|
||||
* @param ch - Index for the channel we want to abort the transfer.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int no_os_dma_xfer_abort(struct no_os_dma_desc *desc, struct no_os_dma_ch *ch)
|
||||
{
|
||||
void *discard;
|
||||
int ret;
|
||||
|
||||
if (!desc || !desc->platform_ops || !ch)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->dma_xfer_abort)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_lock(ch->mutex);
|
||||
|
||||
if (desc->irq_ctrl)
|
||||
no_os_irq_disable(desc->irq_ctrl, ch->irq_num);
|
||||
|
||||
do {
|
||||
ret = no_os_list_get_first(ch->sg_list, &discard);
|
||||
} while (!ret);
|
||||
|
||||
ret = desc->platform_ops->dma_xfer_abort(desc, ch);
|
||||
|
||||
no_os_mutex_unlock(ch->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the state of a DMA channel (free or not).
|
||||
* @param desc - Reference to the DMA controller.
|
||||
* @param ch - Reference to the DMA channel.
|
||||
* @return true if a channel is free, false otherwise.
|
||||
*/
|
||||
bool no_os_dma_is_completed(struct no_os_dma_desc *desc,
|
||||
struct no_os_dma_ch *ch)
|
||||
{
|
||||
(void)desc;
|
||||
|
||||
if (!ch)
|
||||
return -EINVAL;
|
||||
|
||||
return ch->free;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Whether or not there is a transfer in progress on a specific channel.
|
||||
* @param desc - Reference to the DMA controller.
|
||||
* @param ch - Reference to the DMA channel.
|
||||
* @return true if a channel is free, false otherwise.
|
||||
*/
|
||||
bool no_os_dma_in_progress(struct no_os_dma_desc *desc, struct no_os_dma_ch *ch)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!desc || !desc->platform_ops || !ch)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->dma_ch_in_progress)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_lock(ch->mutex);
|
||||
ret = desc->platform_ops->dma_ch_in_progress(desc, ch);
|
||||
no_os_mutex_unlock(ch->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_dma.h
|
||||
* @brief Platform independent function definitions and data types
|
||||
* for the DMA API.
|
||||
* @author Ciprian Regus (ciprian.regus@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2024(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_DMA_H_
|
||||
#define _NO_OS_DMA_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "no_os_list.h"
|
||||
#include "no_os_irq.h"
|
||||
#include "no_os_mutex.h"
|
||||
|
||||
/**
|
||||
* @enum no_os_dma_xfer_type
|
||||
* @brief Supported transfer directions
|
||||
*/
|
||||
enum no_os_dma_xfer_type {
|
||||
MEM_TO_MEM,
|
||||
MEM_TO_DEV,
|
||||
DEV_TO_MEM,
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_dma_default_handler_data
|
||||
* @brief IRQ parameter for the default inter transfer handler
|
||||
*/
|
||||
struct no_os_dma_default_handler_data {
|
||||
struct no_os_dma_desc *desc;
|
||||
struct no_os_dma_ch *channel;
|
||||
void *extra;
|
||||
};
|
||||
|
||||
struct no_os_dma_platform_ops;
|
||||
|
||||
/**
|
||||
* @struct no_os_dma_xfer_desc
|
||||
* @brief It's used to setup a generic DMA transfer.
|
||||
*/
|
||||
struct no_os_dma_xfer_desc {
|
||||
/** Source address for the data */
|
||||
uint8_t *src;
|
||||
/** Destination address for the data */
|
||||
uint8_t *dst;
|
||||
/** Transfer length in bytes */
|
||||
uint32_t length;
|
||||
/** Transfer direction */
|
||||
enum no_os_dma_xfer_type xfer_type;
|
||||
|
||||
/** This function will be called once the transfer completes. */
|
||||
void (*xfer_complete_cb)(struct no_os_dma_xfer_desc *,
|
||||
struct no_os_dma_xfer_desc *,
|
||||
void *);
|
||||
/**
|
||||
* Parameter for the transfer complete callback. This data should
|
||||
* be valid at least until the callback is invoked.
|
||||
*/
|
||||
void *xfer_complete_ctx;
|
||||
/** Transfer complete interrupt priority level */
|
||||
uint32_t irq_priority;
|
||||
|
||||
/**
|
||||
* Peripheral which originated the transfer. Will be used to add
|
||||
* the callback to the proper event list.
|
||||
*/
|
||||
enum no_os_irq_peripheral periph;
|
||||
|
||||
/** User or platform defined data */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_dma_ch
|
||||
* @brief Describes the state of a DMA channel.
|
||||
*/
|
||||
struct no_os_dma_ch {
|
||||
/** Channel number */
|
||||
uint32_t id;
|
||||
/** Whether or not there is a transfer in progress on this channel */
|
||||
bool free;
|
||||
/** List of transfers for this channel */
|
||||
struct no_os_list_desc *sg_list;
|
||||
/** Channel specific interrupt line number */
|
||||
uint32_t irq_num;
|
||||
/** irq callback */
|
||||
struct no_os_callback_desc cb_desc;
|
||||
/** IRQ parameter for the default inter transfer handler */
|
||||
struct no_os_dma_default_handler_data irq_ctx;
|
||||
void *extra;
|
||||
|
||||
/** Used to synchronize channel specific operations */
|
||||
void *mutex;
|
||||
|
||||
/**
|
||||
* Mark the channel as locked, in order to prevent it from being acquired
|
||||
* even if it's free. Used as a synchronization mechanism between channels.
|
||||
*/
|
||||
bool sync_lock;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_dma_desc
|
||||
* @brief Describes the state of the DMA controller.
|
||||
*/
|
||||
struct no_os_dma_desc {
|
||||
/** Unique id of a DMA controller */
|
||||
uint32_t id;
|
||||
/** The number of channels associated with the controller */
|
||||
uint32_t num_ch;
|
||||
/** References to channels associated with the controller */
|
||||
struct no_os_dma_ch *channels;
|
||||
/** Platform specific DMA functions */
|
||||
struct no_os_dma_platform_ops *platform_ops;
|
||||
/**
|
||||
* Interrupt controller configured by the platform specific DMA functions.
|
||||
* May be left uninitialized,Start resulting in the interrupt handler not being
|
||||
* called once a transfer completes. As such, the user (or platform code) has
|
||||
* to provide the cycling mechanism.
|
||||
*/
|
||||
struct no_os_irq_ctrl_desc *irq_ctrl;
|
||||
/** Platform specific data */
|
||||
void *extra;
|
||||
/** Reference counter */
|
||||
uint32_t ref;
|
||||
/** Used to synchronize DMA controller specific operations */
|
||||
void *mutex;
|
||||
|
||||
/**
|
||||
* Interrupt handler function called when a transfer is completed.
|
||||
* It's used to configure the DMA controller for the next transfer in
|
||||
* a channel's list.
|
||||
*/
|
||||
void (*sg_handler)(void *);
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_dma_init_param
|
||||
* @brief Initialization parameter for the DMA controller
|
||||
*/
|
||||
struct no_os_dma_init_param {
|
||||
/** Unique id of a DMA controller */
|
||||
uint32_t id;
|
||||
/** The number of channels associated with the controller */
|
||||
uint32_t num_ch;
|
||||
/** Platform specific DMA functions */
|
||||
struct no_os_dma_platform_ops *platform_ops;
|
||||
/** Platform specific data */
|
||||
void *extra;
|
||||
|
||||
/**
|
||||
* Optional custom scatter gather callback. May be set to NULL in
|
||||
* order to use the default one.
|
||||
*/
|
||||
void (*sg_handler)(void *);
|
||||
/**
|
||||
* Optional custom parameter for the scatter gather callback. Only takes
|
||||
* effect if the handler is also provided.
|
||||
*/
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
/** Initialize a DMA controller. */
|
||||
int no_os_dma_init(struct no_os_dma_desc **,
|
||||
struct no_os_dma_init_param *);
|
||||
|
||||
/** Free the resources allocated by the DMA layer. Disables the DMA controller. */
|
||||
int no_os_dma_remove(struct no_os_dma_desc *);
|
||||
|
||||
/** Acquire a channel and add the transfers to it's SG list. */
|
||||
int no_os_dma_config_xfer(struct no_os_dma_desc *,
|
||||
struct no_os_dma_xfer_desc *,
|
||||
uint32_t,
|
||||
struct no_os_dma_ch *);
|
||||
|
||||
/** Prevent a channel from being acquired, even if it's free. */
|
||||
int no_os_dma_chan_lock(struct no_os_dma_ch *);
|
||||
|
||||
/** Allow a channel to be acquired, in case it's free. */
|
||||
int no_os_dma_chan_unlock(struct no_os_dma_ch *);
|
||||
|
||||
/** Start the DMA transactions for a specific channel. */
|
||||
int no_os_dma_xfer_start(struct no_os_dma_desc *, struct no_os_dma_ch *);
|
||||
|
||||
/**
|
||||
* Stop the DMA transactions for a specific channel and remove the transfers
|
||||
* from the SG list.
|
||||
*/
|
||||
int no_os_dma_xfer_abort(struct no_os_dma_desc *, struct no_os_dma_ch *);
|
||||
|
||||
/**
|
||||
* Check whether a transfer is complete. By default, it requires the interrupt
|
||||
* handler to set the free flag for the channel.
|
||||
*/
|
||||
bool no_os_dma_is_completed(struct no_os_dma_desc *, struct no_os_dma_ch *);
|
||||
|
||||
/** Whether or not a specific channel has an ongoing transfer. */
|
||||
bool no_os_dma_in_progress(struct no_os_dma_desc *, struct no_os_dma_ch *);
|
||||
|
||||
/** Get a free DMA channel. */
|
||||
int no_os_dma_acquire_channel(struct no_os_dma_desc *, struct no_os_dma_ch **);
|
||||
|
||||
/** Free a DMA channel. */
|
||||
int no_os_dma_release_channel(struct no_os_dma_desc *, struct no_os_dma_ch *);
|
||||
|
||||
/**
|
||||
* @struct no_os_irq_platform_ops
|
||||
* @brief Structure holding IRQ function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_dma_platform_ops {
|
||||
/** Initialize platform specific resources for the DMA controller. */
|
||||
int (*dma_init)(struct no_os_dma_desc **, struct no_os_dma_init_param *);
|
||||
/** Remove resources allocated for the DMA controller. */
|
||||
int (*dma_remove)(struct no_os_dma_desc *desc);
|
||||
/** Get a free channel and set it as busy. */
|
||||
int (*dma_acquire_ch)(struct no_os_dma_desc *, uint32_t *);
|
||||
int (*dma_release_ch)(struct no_os_dma_desc *, uint32_t);
|
||||
/** Configure platform specific settings required for the current DMA transfer */
|
||||
int (*dma_config_xfer)(struct no_os_dma_ch *,
|
||||
struct no_os_dma_xfer_desc *);
|
||||
/** Signal the DMA controller to start the transfer. */
|
||||
int (*dma_xfer_start)(struct no_os_dma_desc *, struct no_os_dma_ch *);
|
||||
/** Signal the DMA controller to stop the transfer. */
|
||||
int (*dma_xfer_abort)(struct no_os_dma_desc *, struct no_os_dma_ch *);
|
||||
/** Whether or not a specific channel has an ongoing or future transfer configured */
|
||||
bool (*dma_ch_is_completed)(struct no_os_dma_desc *, struct no_os_dma_ch *);
|
||||
/**
|
||||
* Whether or not a specific channel has an ongoing transfer.
|
||||
* This returns true between transfers.
|
||||
*/
|
||||
bool (*dma_ch_in_progress)(struct no_os_dma_desc *, struct no_os_dma_ch *);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,119 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_eeprom.c
|
||||
* @brief Implementation of the EEPROM APIs
|
||||
* @author Mahesh Phalke (mahesh.phalke@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2022(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include "no_os_eeprom.h"
|
||||
#include "no_os_error.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize the EEPROM
|
||||
* @param desc - EEPROM descriptor
|
||||
* @param param - EEPROM init parameters
|
||||
* @return 0 in case of success, negative error code otherwise
|
||||
*/
|
||||
int32_t no_os_eeprom_init(struct no_os_eeprom_desc **desc,
|
||||
const struct no_os_eeprom_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!param || !param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->init)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = param->platform_ops->init(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by no_os_eeprom_init()
|
||||
* @param desc - EEPROM descriptor
|
||||
* @return 0 in case of success, negative error code otherwise
|
||||
*/
|
||||
int32_t no_os_eeprom_remove(struct no_os_eeprom_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->remove)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->remove(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write the EEPROM data
|
||||
* @param desc - EEPROM descriptor
|
||||
* @param address - EEPROM address/location to write
|
||||
* @param data - EEPROM data (pointer)
|
||||
* @param bytes - Number of data bytes to write
|
||||
* @return 0 in case of success, negative error code otherwise
|
||||
*/
|
||||
int32_t no_os_eeprom_write(struct no_os_eeprom_desc *desc, uint32_t address,
|
||||
uint8_t *data, uint16_t bytes)
|
||||
{
|
||||
if (!desc || !desc->platform_ops || !data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->write)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->write(desc, address, data, bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read the EEPROM data
|
||||
* @param desc - EEPROM descriptor
|
||||
* @param address - EEPROM address/location to read
|
||||
* @param data - EEPROM data (pointer)
|
||||
* @param bytes - Number of data bytes to read
|
||||
* @return 0 in case of success, negative error code otherwise
|
||||
*/
|
||||
int32_t no_os_eeprom_read(struct no_os_eeprom_desc *desc, uint32_t address,
|
||||
uint8_t *data, uint16_t bytes)
|
||||
{
|
||||
if (!desc || !desc->platform_ops || !data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->read)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->read(desc, address, data, bytes);
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_eeprom.h
|
||||
* @brief Header file for EEPROM APIs
|
||||
* @author Mahesh Phalke (mahesh.phalke@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2022(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _NO_OS_EEPROM_H_
|
||||
#define _NO_OS_EEPROM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/* Forward declaration of structure */
|
||||
struct no_os_eeprom_platform_ops;
|
||||
|
||||
/**
|
||||
* @struct no_os_eeprom_init_param
|
||||
* @brief Structure holding the parameters for EEPROM initialization
|
||||
*/
|
||||
struct no_os_eeprom_init_param {
|
||||
/** Device ID */
|
||||
uint32_t device_id;
|
||||
const struct no_os_eeprom_platform_ops *platform_ops;
|
||||
/** EEPROM extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_eeprom_desc
|
||||
* @brief Structure holding the EEPROM descriptor
|
||||
*/
|
||||
struct no_os_eeprom_desc {
|
||||
/** Device ID */
|
||||
uint32_t device_id;
|
||||
const struct no_os_eeprom_platform_ops *platform_ops;
|
||||
/** EEPROM extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_eeprom_platform_ops
|
||||
* @brief Structure holding the EEPROM function pointers that point to the
|
||||
* platform specific function
|
||||
*/
|
||||
struct no_os_eeprom_platform_ops {
|
||||
/** EEPROM initialization function pointer */
|
||||
int32_t (*init)(struct no_os_eeprom_desc **,
|
||||
const struct no_os_eeprom_init_param *);
|
||||
/** EEPROM data write function pointer */
|
||||
int32_t (*write)(struct no_os_eeprom_desc *, uint32_t, uint8_t *, uint16_t);
|
||||
/** EEPROM data read function pointer */
|
||||
int32_t (*read)(struct no_os_eeprom_desc *, uint32_t, uint8_t *, uint16_t);
|
||||
/** EEPROM remove function pointer */
|
||||
int32_t (*remove)(struct no_os_eeprom_desc *);
|
||||
};
|
||||
|
||||
/* Initialize the EEPROM */
|
||||
int32_t no_os_eeprom_init(struct no_os_eeprom_desc **desc,
|
||||
const struct no_os_eeprom_init_param *param);
|
||||
|
||||
/* Write into EEPROM */
|
||||
int32_t no_os_eeprom_write(struct no_os_eeprom_desc *desc, uint32_t address,
|
||||
uint8_t *data, uint16_t bytes);
|
||||
|
||||
/* Read from EEPROM */
|
||||
int32_t no_os_eeprom_read(struct no_os_eeprom_desc *desc, uint32_t address,
|
||||
uint8_t *data, uint16_t bytes);
|
||||
|
||||
/* Free the resources allocated by no_os_eeprom_init() */
|
||||
int32_t no_os_eeprom_remove(struct no_os_eeprom_desc *desc);
|
||||
|
||||
#endif // _NO_OS_EEPROM_H_
|
||||
@@ -0,0 +1,48 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_error.h
|
||||
* @brief Error codes definition
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _NO_OS_ERROR_H_
|
||||
#define _NO_OS_ERROR_H_
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef __NO_OS_ELASTERROR
|
||||
#define __NO_OS_ELASTERROR 2000
|
||||
#endif
|
||||
|
||||
#define NO_OS_EOVERRUN (__NO_OS_ELASTERROR + 1) /* Circular buffer overrun */
|
||||
|
||||
|
||||
#define NO_OS_IS_ERR_VALUE(x) ((x) < 0)
|
||||
|
||||
#endif // _NO_OS_ERROR_H_
|
||||
@@ -0,0 +1,126 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_fifo.c
|
||||
* @brief Implementation of fifo.
|
||||
* @author Cristian Pop (cristian.pop@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "no_os_fifo.h"
|
||||
#include "no_os_error.h"
|
||||
#include "no_os_alloc.h"
|
||||
|
||||
/**
|
||||
* @brief Create new fifo element
|
||||
* @param buff - Data to be saved in fifo.
|
||||
* @param len - Length of the data.
|
||||
* @return fifo element in case of success, NULL otherwise
|
||||
*/
|
||||
static struct no_os_fifo_element * fifo_new_element(char *buff, uint32_t len)
|
||||
{
|
||||
struct no_os_fifo_element *q = no_os_calloc(1,
|
||||
sizeof(struct no_os_fifo_element));
|
||||
if (!q)
|
||||
return NULL;
|
||||
|
||||
q->len = len;
|
||||
q->data = no_os_calloc(1, len);
|
||||
if (!(q->data)) {
|
||||
no_os_free(q);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(q->data, buff, len);
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get last element in fifo
|
||||
* @param p_fifo - pointer to fifo
|
||||
* @return fifo last element if exists, NULL otherwise
|
||||
*/
|
||||
static struct no_os_fifo_element *no_os_fifo_get_last(struct no_os_fifo_element
|
||||
*p_fifo)
|
||||
{
|
||||
if (p_fifo == NULL)
|
||||
return NULL;
|
||||
while (p_fifo->next) {
|
||||
p_fifo = p_fifo->next;
|
||||
}
|
||||
|
||||
return p_fifo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert element to fifo, in the last position.
|
||||
* @param p_fifo - Pointer to fifo.
|
||||
* @param buff - Data to be saved in fifo.
|
||||
* @param len - Length of the data.
|
||||
* @return 0 in case of success, -1 otherwise
|
||||
*/
|
||||
int32_t no_os_fifo_insert(struct no_os_fifo_element **p_fifo, char *buff,
|
||||
uint32_t len)
|
||||
{
|
||||
struct no_os_fifo_element *p, *q;
|
||||
|
||||
if (len <= 0)
|
||||
return -1;
|
||||
|
||||
q = fifo_new_element(buff, len);
|
||||
if (!q)
|
||||
return -1;
|
||||
|
||||
if (!(*p_fifo)) {
|
||||
*p_fifo = q;
|
||||
} else {
|
||||
p = no_os_fifo_get_last(*p_fifo);
|
||||
p->next = q;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove fifo head
|
||||
* @param p_fifo - Pointer to fifo.
|
||||
* @return next element in fifo if exists, NULL otherwise.
|
||||
*/
|
||||
struct no_os_fifo_element * no_os_fifo_remove(struct no_os_fifo_element *p_fifo)
|
||||
{
|
||||
struct no_os_fifo_element *p = p_fifo;
|
||||
|
||||
if (p_fifo != NULL) {
|
||||
p_fifo = p_fifo->next;
|
||||
no_os_free(p->data);
|
||||
no_os_free(p);
|
||||
}
|
||||
|
||||
return p_fifo;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_fifo.h
|
||||
* @brief Header file of fifo
|
||||
* @author Cristian Pop (cristian.pop@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_FIFO_H_
|
||||
#define _NO_OS_FIFO_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @struct no_os_fifo_element
|
||||
* @brief Structure holding the fifo element parameters.
|
||||
*/
|
||||
struct no_os_fifo_element {
|
||||
/** next FIFO element */
|
||||
struct no_os_fifo_element *next;
|
||||
/** FIFO data pointer */
|
||||
char *data;
|
||||
/** FIFO length */
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
/* Insert element to fifo tail. */
|
||||
int32_t no_os_fifo_insert(struct no_os_fifo_element **p_fifo, char *buff,
|
||||
uint32_t len);
|
||||
|
||||
/* Remove fifo head. */
|
||||
struct no_os_fifo_element *no_os_fifo_remove(struct no_os_fifo_element *p_fifo);
|
||||
|
||||
#endif // _NO_OS_FIFO_H_
|
||||
@@ -0,0 +1,96 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_flash.h
|
||||
* @brief Header file for flash controller driver.
|
||||
* @author Andrei Drimbarean (andrei.drimbarean@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2021(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _NO_OS_FLASH_H_
|
||||
#define _NO_OS_FLASH_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @struct no_os_flash_dev
|
||||
* @brief Flash controller device structure
|
||||
*/
|
||||
struct no_os_flash_dev {
|
||||
/** Flash Device ID */
|
||||
uint8_t id;
|
||||
/** Size of flash memory in bytes */
|
||||
uint32_t flash_size;
|
||||
/** Size of flash page in bytes */
|
||||
uint32_t page_size;
|
||||
/** Flash extra parameters */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_flash_init_param
|
||||
* @brief Flash controller initialization structure
|
||||
*/
|
||||
struct no_os_flash_init_param {
|
||||
/** Flash Device ID */
|
||||
uint8_t id;
|
||||
/** Size of flash memory in bytes */
|
||||
uint32_t flash_size;
|
||||
/** Size of flash page in bytes */
|
||||
uint32_t flash_page_size;
|
||||
/** Flash extra parameters */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/** Initialize flash controller. */
|
||||
int32_t no_os_flash_init(struct no_os_flash_dev **device,
|
||||
struct no_os_flash_init_param *init_param);
|
||||
|
||||
/** Free memory allocated by no_os_flash_init(). */
|
||||
int32_t no_os_flash_remove(struct no_os_flash_dev *dev);
|
||||
|
||||
/** Erase a flash page. */
|
||||
int32_t no_os_flash_clear_page(struct no_os_flash_dev *dev, int32_t page_no);
|
||||
|
||||
/** Write a flash page. */
|
||||
int32_t no_os_flash_write_page(struct no_os_flash_dev *dev, int32_t page_no,
|
||||
uint32_t *data);
|
||||
|
||||
/** Read a flash page. */
|
||||
int32_t flash_read_page(struct no_os_flash_dev *dev, int32_t page_no,
|
||||
uint32_t *data);
|
||||
|
||||
/** Write data in flash memory. */
|
||||
int32_t no_os_flash_write(struct no_os_flash_dev *dev, uint32_t flash_addr,
|
||||
uint32_t *array, uint32_t array_size);
|
||||
|
||||
/** Read data from the flash memory. */
|
||||
int32_t no_os_flash_read(struct no_os_flash_dev *dev, uint32_t flash_addr,
|
||||
uint32_t *array,
|
||||
uint32_t size);
|
||||
|
||||
#endif // _NO_OS_FLASH_H_
|
||||
@@ -0,0 +1,166 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_font_8x8.c
|
||||
* @brief Font style for 8x8 characters.
|
||||
* @author Andrei Porumb (andrei.porumb@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2021(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* ASCII to bitmap */
|
||||
const uint8_t no_os_chr_8x8[128][8] = {
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00},
|
||||
{0x64, 0x3c, 0x26, 0x64, 0x3c, 0x26, 0x24, 0x00},
|
||||
{0x26, 0x49, 0x49, 0x7f, 0x49, 0x49, 0x32, 0x00},
|
||||
{0x42, 0x25, 0x12, 0x08, 0x24, 0x52, 0x21, 0x00},
|
||||
{0x20, 0x50, 0x4e, 0x55, 0x22, 0x58, 0x28, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, 0x00},
|
||||
{0x00, 0x15, 0x15, 0x0e, 0x0e, 0x15, 0x15, 0x00},
|
||||
{0x00, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x50, 0x30, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00},
|
||||
{0x00, 0x3e, 0x41, 0x41, 0x41, 0x3e, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x41, 0x7f, 0x40, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x42, 0x61, 0x51, 0x49, 0x6e, 0x00, 0x00},
|
||||
{0x00, 0x22, 0x41, 0x49, 0x49, 0x36, 0x00, 0x00},
|
||||
{0x00, 0x18, 0x14, 0x12, 0x7f, 0x10, 0x00, 0x00},
|
||||
{0x00, 0x27, 0x49, 0x49, 0x49, 0x71, 0x00, 0x00},
|
||||
{0x00, 0x3c, 0x4a, 0x49, 0x48, 0x70, 0x00, 0x00},
|
||||
{0x00, 0x43, 0x21, 0x11, 0x0d, 0x03, 0x00, 0x00},
|
||||
{0x00, 0x36, 0x49, 0x49, 0x49, 0x36, 0x00, 0x00},
|
||||
{0x00, 0x06, 0x09, 0x49, 0x29, 0x1e, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x52, 0x30, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x08, 0x14, 0x14, 0x22, 0x00, 0x00},
|
||||
{0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00},
|
||||
{0x00, 0x00, 0x22, 0x14, 0x14, 0x08, 0x00, 0x00},
|
||||
{0x00, 0x02, 0x01, 0x59, 0x05, 0x02, 0x00, 0x00},
|
||||
{0x3e, 0x41, 0x5d, 0x55, 0x4d, 0x51, 0x2e, 0x00},
|
||||
{0x40, 0x7c, 0x4a, 0x09, 0x4a, 0x7c, 0x40, 0x00},
|
||||
{0x41, 0x7f, 0x49, 0x49, 0x49, 0x49, 0x36, 0x00},
|
||||
{0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x22, 0x00},
|
||||
{0x41, 0x7f, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00},
|
||||
{0x41, 0x7f, 0x49, 0x49, 0x5d, 0x41, 0x63, 0x00},
|
||||
{0x41, 0x7f, 0x49, 0x09, 0x1d, 0x01, 0x03, 0x00},
|
||||
{0x1c, 0x22, 0x41, 0x49, 0x49, 0x3a, 0x08, 0x00},
|
||||
{0x41, 0x7f, 0x08, 0x08, 0x08, 0x7f, 0x41, 0x00},
|
||||
{0x00, 0x41, 0x41, 0x7F, 0x41, 0x41, 0x00, 0x00},
|
||||
{0x30, 0x40, 0x41, 0x41, 0x3F, 0x01, 0x01, 0x00},
|
||||
{0x41, 0x7f, 0x08, 0x0c, 0x12, 0x61, 0x41, 0x00},
|
||||
{0x41, 0x7f, 0x41, 0x40, 0x40, 0x40, 0x60, 0x00},
|
||||
{0x41, 0x7f, 0x42, 0x0c, 0x42, 0x7f, 0x41, 0x00},
|
||||
{0x41, 0x7f, 0x42, 0x0c, 0x11, 0x7f, 0x01, 0x00},
|
||||
{0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00},
|
||||
{0x41, 0x7f, 0x49, 0x09, 0x09, 0x09, 0x06, 0x00},
|
||||
{0x0c, 0x12, 0x21, 0x21, 0x61, 0x52, 0x4c, 0x00},
|
||||
{0x41, 0x7f, 0x09, 0x09, 0x19, 0x69, 0x46, 0x00},
|
||||
{0x66, 0x49, 0x49, 0x49, 0x49, 0x49, 0x33, 0x00},
|
||||
{0x03, 0x01, 0x41, 0x7f, 0x41, 0x01, 0x03, 0x00},
|
||||
{0x01, 0x3f, 0x41, 0x40, 0x41, 0x3f, 0x01, 0x00},
|
||||
{0x01, 0x0f, 0x31, 0x40, 0x31, 0x0f, 0x01, 0x00},
|
||||
{0x01, 0x1f, 0x61, 0x14, 0x61, 0x1f, 0x01, 0x00},
|
||||
{0x41, 0x41, 0x36, 0x08, 0x36, 0x41, 0x41, 0x00},
|
||||
{0x01, 0x03, 0x44, 0x78, 0x44, 0x03, 0x01, 0x00},
|
||||
{0x43, 0x61, 0x51, 0x49, 0x45, 0x43, 0x61, 0x00},
|
||||
{0x00, 0x00, 0x7f, 0x41, 0x41, 0x00, 0x00, 0x00},
|
||||
{0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00},
|
||||
{0x00, 0x00, 0x41, 0x41, 0x7f, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x04, 0x02, 0x01, 0x01, 0x02, 0x04, 0x00},
|
||||
{0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00},
|
||||
{0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x34, 0x4a, 0x4a, 0x4a, 0x3c, 0x40, 0x00},
|
||||
{0x00, 0x41, 0x3f, 0x48, 0x48, 0x48, 0x30, 0x00},
|
||||
{0x00, 0x3c, 0x42, 0x42, 0x42, 0x24, 0x00, 0x00},
|
||||
{0x00, 0x30, 0x48, 0x48, 0x49, 0x3f, 0x40, 0x00},
|
||||
{0x00, 0x3c, 0x4a, 0x4a, 0x4a, 0x2c, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x48, 0x7e, 0x49, 0x09, 0x00, 0x00},
|
||||
{0x00, 0x26, 0x49, 0x49, 0x49, 0x3f, 0x01, 0x00},
|
||||
{0x41, 0x7f, 0x48, 0x04, 0x44, 0x78, 0x40, 0x00},
|
||||
{0x00, 0x00, 0x44, 0x7d, 0x40, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x40, 0x44, 0x3d, 0x00, 0x00, 0x00},
|
||||
{0x41, 0x7f, 0x10, 0x18, 0x24, 0x42, 0x42, 0x00},
|
||||
{0x00, 0x40, 0x41, 0x7f, 0x40, 0x40, 0x00, 0x00},
|
||||
{0x42, 0x7e, 0x02, 0x7c, 0x02, 0x7e, 0x40, 0x00},
|
||||
{0x42, 0x7e, 0x44, 0x02, 0x42, 0x7c, 0x40, 0x00},
|
||||
{0x00, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00},
|
||||
{0x00, 0x41, 0x7f, 0x49, 0x09, 0x09, 0x06, 0x00},
|
||||
{0x00, 0x06, 0x09, 0x09, 0x49, 0x7f, 0x41, 0x00},
|
||||
{0x00, 0x42, 0x7e, 0x44, 0x02, 0x02, 0x04, 0x00},
|
||||
{0x00, 0x64, 0x4a, 0x4a, 0x4a, 0x36, 0x00, 0x00},
|
||||
{0x00, 0x04, 0x3f, 0x44, 0x44, 0x20, 0x00, 0x00},
|
||||
{0x00, 0x02, 0x3e, 0x40, 0x40, 0x22, 0x7e, 0x40},
|
||||
{0x02, 0x0e, 0x32, 0x40, 0x32, 0x0e, 0x02, 0x00},
|
||||
{0x02, 0x1e, 0x62, 0x18, 0x62, 0x1e, 0x02, 0x00},
|
||||
{0x42, 0x62, 0x14, 0x08, 0x14, 0x62, 0x42, 0x00},
|
||||
{0x01, 0x43, 0x45, 0x38, 0x05, 0x03, 0x01, 0x00},
|
||||
{0x00, 0x46, 0x62, 0x52, 0x4a, 0x46, 0x62, 0x00},
|
||||
{0x00, 0x00, 0x08, 0x36, 0x41, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x41, 0x36, 0x08, 0x00, 0x00},
|
||||
{0x00, 0x18, 0x08, 0x08, 0x10, 0x10, 0x18, 0x00},
|
||||
{0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55}
|
||||
};
|
||||
@@ -0,0 +1,231 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_gpio.c
|
||||
* @brief Implementation of the GPIO Interface
|
||||
* @author Antoniu Miclaus (antoniu.miclaus@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "no_os_gpio.h"
|
||||
#include <stdlib.h>
|
||||
#include "no_os_error.h"
|
||||
|
||||
/**
|
||||
* @brief Obtain the GPIO decriptor.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param param - GPIO Initialization parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_gpio_get(struct no_os_gpio_desc **desc,
|
||||
const struct no_os_gpio_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!param || !param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->gpio_ops_get)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = param->platform_ops->gpio_ops_get(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the value of an optional GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param param - GPIO Initialization parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_gpio_get_optional(struct no_os_gpio_desc **desc,
|
||||
const struct no_os_gpio_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!param || (param->number == -1)) {
|
||||
*desc = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->gpio_ops_get_optional)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = param->platform_ops->gpio_ops_get_optional(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* @brief Free the resources allocated by no_os_gpio_get().
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_gpio_remove(struct no_os_gpio_desc *desc)
|
||||
{
|
||||
if (desc) {
|
||||
if (!desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->gpio_ops_remove)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->gpio_ops_remove(desc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the input direction of the specified GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_gpio_direction_input(struct no_os_gpio_desc *desc)
|
||||
{
|
||||
if (desc) {
|
||||
if (!desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->gpio_ops_direction_input)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->gpio_ops_direction_input(desc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the output direction of the specified GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param value - The value.
|
||||
* Example: NO_OS_GPIO_HIGH
|
||||
* NO_OS_GPIO_LOW
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_gpio_direction_output(struct no_os_gpio_desc *desc,
|
||||
uint8_t value)
|
||||
{
|
||||
if (desc) {
|
||||
if (!desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->gpio_ops_direction_output)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->
|
||||
gpio_ops_direction_output(desc, value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the direction of the specified GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param direction - The direction.
|
||||
* Example: NO_OS_GPIO_OUT
|
||||
* NO_OS_GPIO_IN
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_gpio_get_direction(struct no_os_gpio_desc *desc,
|
||||
uint8_t *direction)
|
||||
{
|
||||
if (desc) {
|
||||
if (!desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->gpio_ops_get_direction)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->
|
||||
gpio_ops_get_direction(desc, direction);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the value of the specified GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param value - The value.
|
||||
* Example: NO_OS_GPIO_HIGH
|
||||
* NO_OS_GPIO_LOW
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_gpio_set_value(struct no_os_gpio_desc *desc,
|
||||
uint8_t value)
|
||||
{
|
||||
if (desc) {
|
||||
if (!desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->gpio_ops_set_value)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->gpio_ops_set_value(desc, value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the value of the specified GPIO.
|
||||
* @param desc - The GPIO descriptor.
|
||||
* @param value - The value.
|
||||
* Example: NO_OS_GPIO_HIGH
|
||||
* NO_OS_GPIO_LOW
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_gpio_get_value(struct no_os_gpio_desc *desc,
|
||||
uint8_t *value)
|
||||
{
|
||||
if (desc) {
|
||||
if (!desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->gpio_ops_set_value)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->gpio_ops_get_value(desc, value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_gpio.h
|
||||
* @brief Header file of GPIO Interface
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _NO_OS_GPIO_H_
|
||||
#define _NO_OS_GPIO_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define NO_OS_GPIO_OUT 0x01
|
||||
#define NO_OS_GPIO_IN 0x00
|
||||
|
||||
/**
|
||||
* @struct no_os_gpio_platform_ops
|
||||
* @brief Structure holding gpio function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_gpio_platform_ops ;
|
||||
|
||||
/**
|
||||
* @enum no_os_gpio_pull_up
|
||||
* @brief Enum that holds the possible pull up/ pull down resistor configuration.
|
||||
*/
|
||||
enum no_os_gpio_pull_up {
|
||||
NO_OS_PULL_NONE,
|
||||
/** Strong pull up */
|
||||
NO_OS_PULL_UP,
|
||||
/** Strong pull down */
|
||||
NO_OS_PULL_DOWN,
|
||||
NO_OS_PULL_UP_WEAK,
|
||||
NO_OS_PULL_DOWN_WEAK
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_gpio_init_param
|
||||
* @brief Structure holding the parameters for GPIO initialization.
|
||||
*/
|
||||
struct no_os_gpio_init_param {
|
||||
/** Port number */
|
||||
int32_t port;
|
||||
/** GPIO number */
|
||||
int32_t number;
|
||||
/** Pull up/down resistor configuration */
|
||||
enum no_os_gpio_pull_up pull;
|
||||
/** GPIO platform specific functions */
|
||||
const struct no_os_gpio_platform_ops *platform_ops;
|
||||
/** GPIO extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_gpio_desc
|
||||
* @brief Structure holding the GPIO descriptor.
|
||||
*/
|
||||
struct no_os_gpio_desc {
|
||||
/** Port number */
|
||||
int32_t port;
|
||||
/** GPIO number */
|
||||
int32_t number;
|
||||
/** Pull up/down resistor configuration */
|
||||
enum no_os_gpio_pull_up pull;
|
||||
/** GPIO platform specific functions */
|
||||
const struct no_os_gpio_platform_ops *platform_ops;
|
||||
/** GPIO extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum no_os_gpio_values
|
||||
* @brief Enum that holds the possible output states of a GPIO.
|
||||
*/
|
||||
enum no_os_gpio_values {
|
||||
/** GPIO logic low */
|
||||
NO_OS_GPIO_LOW,
|
||||
/** GPIO logic high */
|
||||
NO_OS_GPIO_HIGH,
|
||||
/** GPIO high impedance */
|
||||
NO_OS_GPIO_HIGH_Z
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_gpio_platform_ops
|
||||
* @brief Structure holding gpio function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_gpio_platform_ops {
|
||||
/** gpio initialization function pointer */
|
||||
int32_t (*gpio_ops_get)(struct no_os_gpio_desc **,
|
||||
const struct no_os_gpio_init_param *);
|
||||
/** gpio optional descriptor function pointer */
|
||||
int32_t (*gpio_ops_get_optional)(struct no_os_gpio_desc **,
|
||||
const struct no_os_gpio_init_param *);
|
||||
/** gpio remove function pointer */
|
||||
int32_t (*gpio_ops_remove)(struct no_os_gpio_desc *);
|
||||
/** gpio direction input function pointer */
|
||||
int32_t (*gpio_ops_direction_input)(struct no_os_gpio_desc *);
|
||||
/** gpio direction output function pointer */
|
||||
int32_t (*gpio_ops_direction_output)(struct no_os_gpio_desc *, uint8_t);
|
||||
/** gpio get direction function pointer */
|
||||
int32_t (*gpio_ops_get_direction)(struct no_os_gpio_desc *, uint8_t *);
|
||||
/** gpio set value function pointer */
|
||||
int32_t (*gpio_ops_set_value)(struct no_os_gpio_desc *, uint8_t);
|
||||
/** gpio get value function pointer */
|
||||
int32_t (*gpio_ops_get_value)(struct no_os_gpio_desc *, uint8_t *);
|
||||
};
|
||||
|
||||
/* Obtain the GPIO decriptor. */
|
||||
int32_t no_os_gpio_get(struct no_os_gpio_desc **desc,
|
||||
const struct no_os_gpio_init_param *param);
|
||||
|
||||
/* Obtain optional GPIO descriptor. */
|
||||
int32_t no_os_gpio_get_optional(struct no_os_gpio_desc **desc,
|
||||
const struct no_os_gpio_init_param *param);
|
||||
|
||||
/* Free the resources allocated by no_os_gpio_get(). */
|
||||
int32_t no_os_gpio_remove(struct no_os_gpio_desc *desc);
|
||||
|
||||
/* Enable the input direction of the specified GPIO. */
|
||||
int32_t no_os_gpio_direction_input(struct no_os_gpio_desc *desc);
|
||||
|
||||
/* Enable the output direction of the specified GPIO. */
|
||||
int32_t no_os_gpio_direction_output(struct no_os_gpio_desc *desc,
|
||||
uint8_t value);
|
||||
|
||||
/* Get the direction of the specified GPIO. */
|
||||
int32_t no_os_gpio_get_direction(struct no_os_gpio_desc *desc,
|
||||
uint8_t *direction);
|
||||
|
||||
/* Set the value of the specified GPIO. */
|
||||
int32_t no_os_gpio_set_value(struct no_os_gpio_desc *desc,
|
||||
uint8_t value);
|
||||
|
||||
/* Get the value of the specified GPIO. */
|
||||
int32_t no_os_gpio_get_value(struct no_os_gpio_desc *desc,
|
||||
uint8_t *value);
|
||||
|
||||
#endif // _NO_OS_GPIO_H_
|
||||
@@ -0,0 +1,209 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_i2c.c
|
||||
* @brief Implementation of the I2C Interface
|
||||
* @author Antoniu Miclaus (antoniu.miclaus@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "no_os_i2c.h"
|
||||
#include <stdlib.h>
|
||||
#include "no_os_error.h"
|
||||
#include "no_os_mutex.h"
|
||||
#include "no_os_alloc.h"
|
||||
|
||||
/**
|
||||
* @brief i2c_table contains the pointers towards the i2c buses
|
||||
*/
|
||||
static void *i2c_table[I2C_MAX_BUS_NUMBER + 1];
|
||||
|
||||
/**
|
||||
* @brief Initialize the I2C communication peripheral.
|
||||
* @param desc - The I2C descriptor.
|
||||
* @param param - The structure that contains the I2C parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_i2c_init(struct no_os_i2c_desc **desc,
|
||||
const struct no_os_i2c_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!param || !param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->i2c_ops_init)
|
||||
return -ENOSYS;
|
||||
if (param->device_id > I2C_MAX_BUS_NUMBER)
|
||||
return -EINVAL;
|
||||
// Initializing BUS descriptor
|
||||
if (i2c_table[param->device_id] == NULL) {
|
||||
ret = no_os_i2cbus_init(param);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
// Initilize I2C descriptor
|
||||
ret = param->platform_ops->i2c_ops_init(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
(*desc)->bus = i2c_table[param->device_id];
|
||||
(*desc)->bus->slave_number++;
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the i2c bus communication peripheral.
|
||||
* @param param - The structure that containes the i2c bus parameters
|
||||
* @return 0 in case of success, error code otherwise
|
||||
*/
|
||||
int32_t no_os_i2cbus_init(const struct no_os_i2c_init_param *param)
|
||||
{
|
||||
struct no_os_i2cbus_desc *bus = (struct no_os_i2cbus_desc *)no_os_calloc(1,
|
||||
sizeof(struct no_os_i2cbus_desc));
|
||||
|
||||
if (!bus)
|
||||
return -ENOMEM;
|
||||
|
||||
no_os_mutex_init(&(bus->mutex));
|
||||
|
||||
bus->slave_number = 0;
|
||||
bus->device_id = param->device_id;
|
||||
bus->max_speed_hz = param->max_speed_hz;
|
||||
bus->platform_ops = param->platform_ops;
|
||||
bus->extra = param->extra;
|
||||
|
||||
i2c_table[param->device_id] = bus;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by no_os_i2c_init().
|
||||
* @param desc - The I2C descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_i2c_remove(struct no_os_i2c_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (desc->bus)
|
||||
no_os_i2cbus_remove(desc->bus->device_id);
|
||||
|
||||
if (!desc->platform_ops->i2c_ops_remove)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->i2c_ops_remove(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes i2c bus instance
|
||||
* @param bus_number - i2c bus number
|
||||
*/
|
||||
void no_os_i2cbus_remove(uint32_t bus_number)
|
||||
{
|
||||
struct no_os_i2cbus_desc *bus = (struct no_os_i2cbus_desc *)
|
||||
i2c_table[bus_number];
|
||||
|
||||
if (bus->slave_number > 0)
|
||||
bus->slave_number--;
|
||||
|
||||
if (bus->slave_number == 0) {
|
||||
no_os_mutex_remove(bus->mutex);
|
||||
|
||||
if (bus != NULL) {
|
||||
no_os_free(bus);
|
||||
i2c_table[bus_number] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2C Write data to slave device.
|
||||
* @param desc - The I2C descriptor.
|
||||
* @param data - The buffer with the transmitted/received data.
|
||||
* @param bytes_number - Number of bytes to write.
|
||||
* @param stop_bit - Stop conditional control.
|
||||
* Example: 0 - A stop condition will not be generated.
|
||||
* 1 - A stop condition will be generated.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_i2c_write(struct no_os_i2c_desc *desc,
|
||||
uint8_t *data,
|
||||
uint8_t bytes_number,
|
||||
uint8_t stop_bit)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->i2c_ops_write)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_lock(desc->bus->mutex);
|
||||
ret = desc->platform_ops->i2c_ops_write(desc, data, bytes_number,
|
||||
stop_bit);
|
||||
no_os_mutex_unlock(desc->bus->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2C Read data from slave device.
|
||||
* @param desc - The i2c descriptor.
|
||||
* @param data - The buffer with the transmitted/received data.
|
||||
* @param bytes_number - Number of bytes to read.
|
||||
* @param stop_bit - Stop conditional control.
|
||||
* Example: 0 - A stop condition will not be generated.
|
||||
* 1 - A stop condition will be generated.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_i2c_read(struct no_os_i2c_desc *desc,
|
||||
uint8_t *data,
|
||||
uint8_t bytes_number,
|
||||
uint8_t stop_bit)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->i2c_ops_read)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_lock(desc->bus->mutex);
|
||||
ret = desc->platform_ops->i2c_ops_read(desc, data, bytes_number,
|
||||
stop_bit);
|
||||
no_os_mutex_unlock(desc->bus->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_i2c.h
|
||||
* @brief Header file of I2C Interface
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _NO_OS_I2C_H_
|
||||
#define _NO_OS_I2C_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define I2C_MAX_BUS_NUMBER 4
|
||||
|
||||
/**
|
||||
* @struct no_os_i2c_platform_ops
|
||||
* @brief Structure holding I2C function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_i2c_platform_ops ;
|
||||
|
||||
/**
|
||||
* @struct no_os_i2c_init_param
|
||||
* @brief Structure holding the parameters for I2C initialization.
|
||||
*/
|
||||
struct no_os_i2c_init_param {
|
||||
/** Device ID */
|
||||
uint32_t device_id;
|
||||
/** I2C maximum transfer speed supported */
|
||||
uint32_t max_speed_hz;
|
||||
/** Slave address */
|
||||
uint8_t slave_address;
|
||||
/** I2C platform specific functions */
|
||||
const struct no_os_i2c_platform_ops *platform_ops;
|
||||
/** I2C extra parameters (device specific parameters) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_i2cbus_desc
|
||||
* @brief Structure holding I2C bus descriptor
|
||||
*/
|
||||
struct no_os_i2cbus_desc {
|
||||
/** I2C bus mutex(lock)*/
|
||||
void* mutex;
|
||||
/** I2C bus slave number*/
|
||||
uint8_t slave_number;
|
||||
/** I2C bus Device ID */
|
||||
uint32_t device_id;
|
||||
/** I2C bus maximum transfer speed supported */
|
||||
uint32_t max_speed_hz;
|
||||
/** I2C bus platform specific functions */
|
||||
const struct no_os_i2c_platform_ops *platform_ops;
|
||||
/** I2C bus extra parameters (device specific parameters) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @struct no_os_i2c_desc
|
||||
* @brief Structure holding I2C address descriptor
|
||||
*/
|
||||
struct no_os_i2c_desc {
|
||||
/** I2C bus address*/
|
||||
struct no_os_i2cbus_desc *bus;
|
||||
/** Device ID */
|
||||
uint32_t device_id;
|
||||
/** I2C maximum transfer speed supported */
|
||||
uint32_t max_speed_hz;
|
||||
/** Slave address */
|
||||
uint8_t slave_address;
|
||||
/** I2C platform specific functions */
|
||||
const struct no_os_i2c_platform_ops *platform_ops;
|
||||
/** I2C extra parameters (device specific parameters) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_i2c_platform_ops
|
||||
* @brief Structure holding i2c function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_i2c_platform_ops {
|
||||
/** i2c initialization function pointer */
|
||||
int32_t (*i2c_ops_init)(struct no_os_i2c_desc **,
|
||||
const struct no_os_i2c_init_param *);
|
||||
/** i2c write function pointer */
|
||||
int32_t (*i2c_ops_write)(struct no_os_i2c_desc *, uint8_t *, uint8_t, uint8_t);
|
||||
/** i2c write function pointer */
|
||||
int32_t (*i2c_ops_read)(struct no_os_i2c_desc *, uint8_t *, uint8_t, uint8_t);
|
||||
/** i2c remove function pointer */
|
||||
int32_t (*i2c_ops_remove)(struct no_os_i2c_desc *);
|
||||
};
|
||||
|
||||
/* Initialize the I2C communication peripheral. */
|
||||
int32_t no_os_i2c_init(struct no_os_i2c_desc **desc,
|
||||
const struct no_os_i2c_init_param *param);
|
||||
|
||||
/* Free the resources allocated by no_os_i2c_init(). */
|
||||
int32_t no_os_i2c_remove(struct no_os_i2c_desc *desc);
|
||||
|
||||
/* Write data to a slave device. */
|
||||
int32_t no_os_i2c_write(struct no_os_i2c_desc *desc,
|
||||
uint8_t *data,
|
||||
uint8_t bytes_number,
|
||||
uint8_t stop_bit);
|
||||
|
||||
/* Read data from a slave device. */
|
||||
int32_t no_os_i2c_read(struct no_os_i2c_desc *desc,
|
||||
uint8_t *data,
|
||||
uint8_t bytes_number,
|
||||
uint8_t stop_bit);
|
||||
|
||||
/* Initialize I2C bus descriptor*/
|
||||
int32_t no_os_i2cbus_init(const struct no_os_i2c_init_param *param);
|
||||
|
||||
/* Free the resources allocated for I2C bus desc*/
|
||||
void no_os_i2cbus_remove(uint32_t bus_number);
|
||||
|
||||
#endif // _NO_OS_I2C_H_
|
||||
@@ -0,0 +1,698 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_i3c.c
|
||||
* @brief Implementation of the I3C Interface
|
||||
* @author Jorge Marques (jorge.marques@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2024(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "no_os_i3c.h"
|
||||
#include "no_os_error.h"
|
||||
#include "no_os_mutex.h"
|
||||
#include "no_os_alloc.h"
|
||||
|
||||
/**
|
||||
* @brief i3c_table contains the pointers towards the I3C buses.
|
||||
*/
|
||||
struct no_os_i3c_bus_desc *i3c_table [NO_OS_I3C_MAX_BUS_NUMBER + 1] = {NULL};
|
||||
|
||||
static enum no_os_i3c_slot_status no_os_i3c_addr_get_status(
|
||||
struct no_os_i3c_bus_desc *desc, uint8_t addr);
|
||||
static bool no_os_i3c_addr_is_avail(struct no_os_i3c_bus_desc *desc,
|
||||
uint8_t addr);
|
||||
static void no_os_i3c_addr_init(struct no_os_i3c_bus_desc *desc);
|
||||
|
||||
/**
|
||||
* @brief Initialize the I3C device.
|
||||
* If the bus of the I3C device is not initialized, it will call to init it.
|
||||
* @param desc - The I3C device descriptor.
|
||||
* @param param - The structure that contains the I3C device parameters, to match PID.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int no_os_i3c_init(struct no_os_i3c_desc **desc,
|
||||
const struct no_os_i3c_init_param *param)
|
||||
{
|
||||
int ret;
|
||||
struct no_os_i3c_desc *device_desc;
|
||||
struct no_os_i3c_bus_desc **bus_desc;
|
||||
struct no_os_i3c_bus_init_param *param_bus;
|
||||
struct no_os_i3c_desc **it;
|
||||
uint8_t i;
|
||||
|
||||
if (!param->bus->device_id ||
|
||||
param->bus->device_id > NO_OS_I3C_MAX_BUS_NUMBER)
|
||||
|
||||
return -EINVAL;
|
||||
|
||||
bus_desc = &i3c_table[param->bus->device_id - 1];
|
||||
if (!*bus_desc) {
|
||||
/* Initialize bus if not already */
|
||||
ret = no_os_i3c_init_bus(bus_desc, param->bus);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize device */
|
||||
param_bus = param->bus;
|
||||
|
||||
device_desc = (struct no_os_i3c_desc *)no_os_malloc(
|
||||
sizeof(struct no_os_i3c_desc));
|
||||
if (!device_desc)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Set is_attached flag */
|
||||
if (!param->is_i3c || param->is_static)
|
||||
device_desc->is_attached = 1;
|
||||
else {
|
||||
for (i = 0; i < NO_OS_I3C_MAX_DEV_NUMBER; i++) {
|
||||
if ((*bus_desc)->daa_candidates[i].pid == param->pid)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == NO_OS_I3C_MAX_DEV_NUMBER) {
|
||||
ret = -EFAULT;
|
||||
goto error_device;
|
||||
}
|
||||
device_desc->is_attached = (*bus_desc)->daa_candidates[i].is_attached;
|
||||
if (!device_desc->is_attached) {
|
||||
ret = -EPERM;
|
||||
goto error_device;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy from init param to dev descriptor */
|
||||
device_desc->pid = param->pid;
|
||||
device_desc->addr = param->addr;
|
||||
device_desc->is_static = param->is_static;
|
||||
device_desc->is_i3c = param->is_i3c;
|
||||
device_desc->platform_ops = param_bus->platform_ops;
|
||||
device_desc->bus = *bus_desc;
|
||||
device_desc->event_callback = NULL;
|
||||
|
||||
/* Find free slot */
|
||||
it = (*bus_desc)->devs;
|
||||
while (it < (*bus_desc)->devs + NO_OS_I3C_MAX_DEV_NUMBER) {
|
||||
if (!*it)
|
||||
break;
|
||||
it++;
|
||||
};
|
||||
if (it == (*bus_desc)->devs + NO_OS_I3C_MAX_DEV_NUMBER)
|
||||
goto error_device;
|
||||
|
||||
*it = device_desc;
|
||||
|
||||
ret = device_desc->platform_ops->i3c_ops_init(device_desc, param);
|
||||
if (ret)
|
||||
goto error_device;
|
||||
|
||||
ret = device_desc->platform_ops->i3c_ops_is_dev_ready(device_desc);
|
||||
if (ret)
|
||||
goto error_device;
|
||||
|
||||
*desc = device_desc;
|
||||
return 0;
|
||||
|
||||
error_device:
|
||||
no_os_free(device_desc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the I3C bus.
|
||||
* @param desc - The I3C bus descriptor.
|
||||
* @param param - The structure that contains the I3C bus parameters.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int no_os_i3c_init_bus(struct no_os_i3c_bus_desc **desc,
|
||||
const struct no_os_i3c_bus_init_param *param)
|
||||
{
|
||||
struct no_os_i3c_bus_desc *bus_desc;
|
||||
bool has_static_i3c_addr = 0;
|
||||
int ret;
|
||||
int i = 0;
|
||||
uint8_t data;
|
||||
const struct no_os_i3c_init_param **it;
|
||||
|
||||
if (!param || !param->platform_ops)
|
||||
return -EINVAL;
|
||||
if (!param->platform_ops->i3c_ops_init_bus ||
|
||||
!param->platform_ops->i3c_ops_remove_bus)
|
||||
return -ENOSYS;
|
||||
|
||||
bus_desc = (struct no_os_i3c_bus_desc *)no_os_calloc(1,
|
||||
sizeof(struct no_os_i3c_bus_desc));
|
||||
if (!bus_desc)
|
||||
return -ENOMEM;
|
||||
|
||||
bus_desc->device_id = param->device_id;
|
||||
bus_desc->num_devs = param->num_devs;
|
||||
bus_desc->num_devs_unknown = 0;
|
||||
bus_desc->async_irq = 0;
|
||||
bus_desc->platform_ops = param->platform_ops;
|
||||
|
||||
/*
|
||||
* Execute the platform specific init routine,
|
||||
* which allocate the extra features.
|
||||
*/
|
||||
ret = param->platform_ops->i3c_ops_init_bus(bus_desc, param);
|
||||
if (ret)
|
||||
goto error_bus_1;
|
||||
|
||||
i3c_table[param->device_id - 1] = bus_desc;
|
||||
|
||||
no_os_i3c_addr_init(bus_desc);
|
||||
|
||||
/*
|
||||
* Set status for addr, and
|
||||
* If a device supports static addr, set it with CCC STAASA.
|
||||
* If not, add to the PID-DA LUT for the DAA procedure.
|
||||
*/
|
||||
for (it = param->devs; it < param->devs + param->num_devs; it++) {
|
||||
if (!*it)
|
||||
continue;
|
||||
|
||||
if (!no_os_i3c_addr_is_avail(bus_desc, (*it)->addr)) {
|
||||
ret = -EINVAL;
|
||||
goto error_bus_2;
|
||||
}
|
||||
|
||||
if ((*it)->is_i3c) {
|
||||
if ((*it)->is_static) {
|
||||
has_static_i3c_addr = 1;
|
||||
no_os_i3c_addr_set_status(bus_desc, (*it)->addr,
|
||||
NO_OS_I3C_ADDR_SLOT_I3C_DEV);
|
||||
} else {
|
||||
bus_desc->daa_candidates[i].pid = (*it)->pid;
|
||||
bus_desc->daa_candidates[i].addr = (*it)->addr;
|
||||
i++;
|
||||
}
|
||||
} else
|
||||
no_os_i3c_addr_set_status(bus_desc, (*it)->addr,
|
||||
NO_OS_I3C_ADDR_SLOT_I2C_DEV);
|
||||
}
|
||||
|
||||
/* Ensure other candidates fields are empty */
|
||||
memset(&bus_desc->daa_candidates[i], 0,
|
||||
sizeof(struct no_os_i3c_daa_lut) * (NO_OS_I3C_MAX_DEV_NUMBER - i));
|
||||
|
||||
/* Reset fully every device on the bus */
|
||||
data = NO_OS_I3C_CCC_RSTACT_WHOLE_TARGET;
|
||||
ret = no_os_i3c_send_ccc(*desc,
|
||||
NO_OS_I3C_BCAST_ADDR,
|
||||
NO_OS_I3C_CCC_RSTACT_BCAST, &data);
|
||||
if (ret)
|
||||
goto error_bus_2;
|
||||
/* Set I3C devices that support static addresses to use them */
|
||||
if (has_static_i3c_addr) {
|
||||
ret = no_os_i3c_send_ccc(bus_desc, NO_OS_I3C_BCAST_ADDR, NO_OS_I3C_CCC_SETAASA,
|
||||
NULL);
|
||||
if (ret)
|
||||
goto error_bus_2;
|
||||
}
|
||||
|
||||
ret = no_os_i3c_do_daa(bus_desc, 1);
|
||||
if (ret)
|
||||
goto error_bus_2;
|
||||
|
||||
no_os_mutex_init(bus_desc->mutex);
|
||||
*desc = bus_desc;
|
||||
|
||||
return 0;
|
||||
|
||||
error_bus_2:
|
||||
ret = param->platform_ops->i3c_ops_remove_bus(bus_desc);
|
||||
error_bus_1:
|
||||
no_os_free(bus_desc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by no_os_i3c_init().
|
||||
* @param desc - The I3C device descriptor.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int no_os_i3c_remove(struct no_os_i3c_desc *desc)
|
||||
{
|
||||
struct no_os_i3c_bus_desc *bus_desc;
|
||||
struct no_os_i3c_desc **it;
|
||||
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->i3c_ops_remove)
|
||||
return -ENOSYS;
|
||||
|
||||
bus_desc = desc->bus;
|
||||
it = bus_desc->devs;
|
||||
while (it < bus_desc->devs + NO_OS_I3C_MAX_DEV_NUMBER) {
|
||||
if (*it == desc)
|
||||
*it = NULL;
|
||||
it++;
|
||||
}
|
||||
|
||||
/* Only error case is !desc */
|
||||
desc->platform_ops->i3c_ops_remove(desc);
|
||||
no_os_free(desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by no_os_i3c_init_bus.
|
||||
* Must remove all devices first, if not, -EFAULT is returned.
|
||||
* @param desc - The I3C bus descriptor.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int no_os_i3c_remove_bus(struct no_os_i3c_bus_desc *desc)
|
||||
{
|
||||
struct no_os_i3c_desc **it;
|
||||
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->i3c_ops_remove_bus)
|
||||
return -ENOSYS;
|
||||
|
||||
/* Verify if all devices are removed */
|
||||
for (it = desc->devs; it < desc->devs + NO_OS_I3C_MAX_DEV_NUMBER; it++) {
|
||||
if (*it)
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
no_os_mutex_remove(desc->mutex);
|
||||
|
||||
/* Only error case is !desc */
|
||||
desc->platform_ops->i3c_ops_remove_bus(desc);
|
||||
|
||||
i3c_table[desc->device_id - 1] = NULL;
|
||||
no_os_free(desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Do DAA to assign the dynamic addresses.
|
||||
* @param desc - The I3C descriptor.
|
||||
* @param rstdaa - Do RSTDAA CCC before the DAA.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int no_os_i3c_do_daa(struct no_os_i3c_bus_desc *desc, bool rstdaa)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->i3c_ops_do_daa)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->i3c_ops_do_daa(desc, rstdaa);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send CCC, either to a device device or broadcast to all.
|
||||
* @param desc - The I3C descriptor.
|
||||
* @param addr - Device address or broadcast address.
|
||||
* @param ccc - CCC RnW, CCC Length, CCC ID.
|
||||
* @param data - The buffer with the transmitted/received data.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int no_os_i3c_send_ccc(struct no_os_i3c_bus_desc *desc,
|
||||
uint8_t addr,
|
||||
uint32_t ccc,
|
||||
uint8_t *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->i3c_ops_send_ccc)
|
||||
return -ENOSYS;
|
||||
|
||||
if ((NO_OS_I3C_CCC_GET_RNW(ccc) && addr == NO_OS_I3C_BCAST_ADDR) ||
|
||||
((addr == NO_OS_I3C_BCAST_ADDR) && (ccc & NO_OS_I3C_CCC_DIRECT)) ||
|
||||
((addr != NO_OS_I3C_BCAST_ADDR) && !(ccc & NO_OS_I3C_CCC_DIRECT)))
|
||||
return -EINVAL;
|
||||
|
||||
no_os_mutex_lock(desc->mutex);
|
||||
ret = desc->platform_ops->i3c_ops_send_ccc(desc, addr, NO_OS_I3C_CCC_ADDR(ccc),
|
||||
NO_OS_I3C_CCC_GET_RNW(ccc), NO_OS_I3C_CCC_GET_DEF(ccc),
|
||||
data, NO_OS_I3C_CCC_GET_LEN(ccc));
|
||||
no_os_mutex_unlock(desc->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send CCC to device device.
|
||||
* @param desc - The I3C descriptor.
|
||||
* @param ccc - CCC RnW, CCC length, CCC id.
|
||||
* @param data - The buffer with the transmitted/received data.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int no_os_i3c_send_direct_ccc(struct no_os_i3c_desc *desc,
|
||||
uint32_t ccc,
|
||||
uint8_t *data)
|
||||
{
|
||||
if (!desc || !desc->bus)
|
||||
return -EINVAL;
|
||||
if (!(ccc & NO_OS_I3C_CCC_DIRECT))
|
||||
return -EINVAL;
|
||||
|
||||
return no_os_i3c_send_ccc(desc->bus, desc->addr, ccc, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write data to device device.
|
||||
* @param desc - The I3C descriptor.
|
||||
* @param data - The buffer with the transmitted data.
|
||||
* @param size - Number of bytes to write.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int no_os_i3c_write(struct no_os_i3c_desc *desc,
|
||||
uint8_t *data,
|
||||
uint8_t size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->i3c_ops_write)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_lock(desc->bus->mutex);
|
||||
ret = desc->bus->platform_ops->i3c_ops_write(desc,
|
||||
data, size);
|
||||
no_os_mutex_unlock(desc->bus->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read data from device device.
|
||||
* @param desc - The I3C descriptor.
|
||||
* @param data - The buffer with the received data.
|
||||
* @param size - Number of bytes to read.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int no_os_i3c_read(struct no_os_i3c_desc *desc,
|
||||
uint8_t *data,
|
||||
uint8_t size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->i3c_ops_read)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_lock(desc->bus->mutex);
|
||||
ret = desc->bus->platform_ops->i3c_ops_read(desc,
|
||||
data, size);
|
||||
no_os_mutex_unlock(desc->bus->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read and write the device.
|
||||
* @param desc - The I3C descriptor.
|
||||
* @param tx_data - The buffer with the transmitted data.
|
||||
* @param tx_data_len - Number of bytes to write.
|
||||
* @param rx_data - The buffer with the received data.
|
||||
* @param rx_data_len - Number of bytes to read.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int no_os_i3c_write_and_read(struct no_os_i3c_desc *desc,
|
||||
uint8_t *tx_data,
|
||||
uint8_t tx_data_len,
|
||||
uint8_t *rx_data,
|
||||
uint8_t rx_data_len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->i3c_ops_read)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_lock(desc->bus->mutex);
|
||||
ret = desc->bus->platform_ops->i3c_ops_write_and_read(desc,
|
||||
tx_data, tx_data_len, rx_data, rx_data_len);
|
||||
no_os_mutex_unlock(desc->bus->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure I3C interrupts.
|
||||
* @param desc - The I3C descriptor.
|
||||
* @param irq - The interrupt type to enable.
|
||||
* @param en - 1 to enable, 0 to disable irq type.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int no_os_i3c_conf_irq(struct no_os_i3c_bus_desc *desc,
|
||||
uint8_t irq, bool en)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->i3c_ops_conf_irq)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->i3c_ops_conf_irq(desc, irq, en);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable I3C non-blocking interrupts.
|
||||
* @param desc - The I3C descriptor.
|
||||
* @param en - 1 to enable, 0 to disable async callback.
|
||||
* @return 0 in case of success, -EINVAL otherwise.
|
||||
*/
|
||||
int no_os_i3c_async_irq(struct no_os_i3c_bus_desc *desc, bool en)
|
||||
{
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
desc->async_irq = en;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait I3C interrupt.
|
||||
* Set async_irq on call to false to ensure single entry point.
|
||||
* @param desc - The I3C descriptor.
|
||||
* @param irq - The interrupt to wait for.
|
||||
* @return 0 in case of success, -EINVAL if in async mode or error codes.
|
||||
*/
|
||||
int no_os_i3c_wait_irq(struct no_os_i3c_bus_desc* desc,
|
||||
uint8_t irq)
|
||||
{
|
||||
if (!desc || desc->async_irq)
|
||||
return -EINVAL;
|
||||
|
||||
while (!(desc->irq_events & irq)) {}
|
||||
|
||||
return no_os_i3c_call_irq(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Non-blocking I3C interrupt.
|
||||
* Since a payload is always retrieved with it, also update the no_os_i3c_ccc_info fields.
|
||||
* @param desc - The I3C descriptor.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int no_os_i3c_call_irq(struct no_os_i3c_bus_desc* desc)
|
||||
{
|
||||
struct no_os_i3c_desc **it;
|
||||
int ret;
|
||||
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->i3c_ops_get_ccc_info)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = desc->platform_ops->i3c_ops_get_ccc_info(desc, desc->irq_events);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
it = desc->devs;
|
||||
while (it < desc->devs + NO_OS_I3C_MAX_DEV_NUMBER) {
|
||||
if (*it && (*it)->addr == desc->ccc_info.ibi_cr_addr) {
|
||||
if ((*it)->event_callback) {
|
||||
(*it)->event_callback((*it), desc->ccc_info.ibi_payload,
|
||||
desc->ccc_info.ibi_payload_len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
it++;
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a free address.
|
||||
* @param desc - The I3C bus descriptor.
|
||||
* @param start_addr - Start address to search from.
|
||||
* @return The free address or 0 if no address is available.
|
||||
*/
|
||||
uint8_t no_os_i3c_addr_get_free(struct no_os_i3c_bus_desc *desc,
|
||||
uint8_t start_addr)
|
||||
{
|
||||
enum no_os_i3c_slot_status status;
|
||||
uint8_t addr;
|
||||
|
||||
for (addr = start_addr; addr < NO_OS_I3C_MAX_ADDR; addr++) {
|
||||
status = no_os_i3c_addr_get_status(desc, addr);
|
||||
if (status == NO_OS_I3C_ADDR_SLOT_FREE)
|
||||
return addr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set status of an address.
|
||||
* @param desc - The I3C bus descriptor.
|
||||
* @param addr - The address to set.
|
||||
* @param status - The value to write.
|
||||
*/
|
||||
void no_os_i3c_addr_set_status(struct no_os_i3c_bus_desc *desc,
|
||||
uint8_t addr, enum no_os_i3c_slot_status status)
|
||||
{
|
||||
unsigned int slot, bitpos;
|
||||
unsigned int *ptr;
|
||||
|
||||
if (addr > NO_OS_I3C_I2C_MAX_ADDR)
|
||||
return;
|
||||
|
||||
slot = NO_OS_I3C_ADDR_GET_SLOT(addr);
|
||||
bitpos = NO_OS_I3C_ADDR_GET_POS(addr);
|
||||
|
||||
ptr = desc->addrslots + slot;
|
||||
// Unset old value
|
||||
*ptr &= ~(NO_OS_I3C_ADDR_SLOT_STATUS_MASK << bitpos);
|
||||
// Set new value
|
||||
*ptr |= (status & NO_OS_I3C_ADDR_SLOT_STATUS_MASK) << bitpos;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get status of an address.
|
||||
* @param desc - The I3C bus descriptor.
|
||||
* @param start_addr - Start address to search from.
|
||||
* @return The free address or -ENOMEM if no available address.
|
||||
*/
|
||||
static enum no_os_i3c_slot_status no_os_i3c_addr_get_status(
|
||||
struct no_os_i3c_bus_desc *desc, uint8_t addr)
|
||||
{
|
||||
unsigned int slot, bitpos;
|
||||
enum no_os_i3c_slot_status status;
|
||||
|
||||
if (addr > NO_OS_I3C_I2C_MAX_ADDR)
|
||||
return NO_OS_I3C_ADDR_SLOT_RSVD;
|
||||
|
||||
slot = NO_OS_I3C_ADDR_GET_SLOT(addr);
|
||||
bitpos = NO_OS_I3C_ADDR_GET_POS(addr);
|
||||
|
||||
status = desc->addrslots[slot];
|
||||
status >>= bitpos;
|
||||
|
||||
return status & NO_OS_I3C_ADDR_SLOT_STATUS_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if address is available.
|
||||
* @param desc - The I3C bus descriptor.
|
||||
* @param addr - Address to check.
|
||||
* @return 1 if available, 0 if not.
|
||||
*/
|
||||
static bool no_os_i3c_addr_is_avail(struct no_os_i3c_bus_desc *desc,
|
||||
uint8_t addr)
|
||||
{
|
||||
enum no_os_i3c_slot_status status;
|
||||
|
||||
status = no_os_i3c_addr_get_status(desc, addr);
|
||||
|
||||
return status == NO_OS_I3C_ADDR_SLOT_FREE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize address buffer, reserving reserved addresses.
|
||||
* @param desc - The I3C bus descriptor.
|
||||
*/
|
||||
static void no_os_i3c_addr_init(struct no_os_i3c_bus_desc *desc)
|
||||
{
|
||||
/* Addresses 0 to 7 are reserved. */
|
||||
for (int i = 0; i < 8; i++)
|
||||
no_os_i3c_addr_set_status(desc, i, NO_OS_I3C_ADDR_SLOT_RSVD);
|
||||
|
||||
/*
|
||||
* Reserve broadcast address and all addresses that might collide
|
||||
* with the broadcast address when facing a single bit error.
|
||||
*/
|
||||
no_os_i3c_addr_set_status(desc, NO_OS_I3C_BCAST_ADDR,
|
||||
NO_OS_I3C_ADDR_SLOT_RSVD);
|
||||
for (int i = 0; i < 7; i++)
|
||||
no_os_i3c_addr_set_status(desc, NO_OS_I3C_BCAST_ADDR ^ NO_OS_BIT(i),
|
||||
NO_OS_I3C_ADDR_SLOT_RSVD);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attach event callback.
|
||||
* @param desc - The I3C device descriptor.
|
||||
* @param callback - Method to call on event.
|
||||
*/
|
||||
void no_os_i3c_attach_callback(struct no_os_i3c_desc *desc,
|
||||
void (*callback)(struct no_os_i3c_desc*, uint32_t, uint32_t))
|
||||
{
|
||||
desc->event_callback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Detach event callback.
|
||||
* @param desc - The I3C device descriptor.
|
||||
*/
|
||||
void no_os_i3c_detach_callback(struct no_os_i3c_desc *desc)
|
||||
{
|
||||
no_os_i3c_attach_callback(desc, NULL);
|
||||
}
|
||||
@@ -0,0 +1,396 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_i3c.h
|
||||
* @brief Header file of I3C Interface
|
||||
* @author Jorge Marques (jorge.marques@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2024(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _NO_OS_I3C_H_
|
||||
#define _NO_OS_I3C_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "no_os_util.h"
|
||||
|
||||
#define NO_OS_I3C_MAX_BUS_NUMBER 3
|
||||
#define NO_OS_I3C_MAX_DEV_NUMBER 15
|
||||
/* I²C/I3C address are 7-bit (not considering extended 10-bit I²C) */
|
||||
#define NO_OS_I3C_I2C_MAX_ADDR 0x7F
|
||||
#define NO_OS_I3C_MAX_ADDR NO_OS_I3C_I2C_MAX_ADDR
|
||||
#define NO_OS_I3C_BCAST_ADDR 0x7E
|
||||
/* 2-bit flags packed in addrslots */
|
||||
#define NO_OS_I3C_ADDR_FLAG_SIZE 2
|
||||
#define NO_OS_I3C_ADDR_PER_SLOT ((unsigned int)(sizeof(unsigned int)*8 / NO_OS_I3C_ADDR_FLAG_SIZE))
|
||||
#define NO_OS_I3C_ADDR_GET_SLOT(x) ((x) / NO_OS_I3C_ADDR_PER_SLOT)
|
||||
#define NO_OS_I3C_ADDR_GET_POS(x) (((x) % NO_OS_I3C_ADDR_PER_SLOT) * NO_OS_I3C_ADDR_FLAG_SIZE)
|
||||
#define NO_OS_I3C_ADDRSLOTS_SIZE \
|
||||
(NO_OS_I3C_I2C_MAX_ADDR / NO_OS_I3C_ADDR_PER_SLOT) + !!(NO_OS_I3C_I2C_MAX_ADDR % NO_OS_I3C_ADDR_PER_SLOT)
|
||||
|
||||
/* I3C CCC (Common Command Codes) related definitions */
|
||||
#define NO_OS_I3C_CCC_BCAST 0
|
||||
#define NO_OS_I3C_CCC_DIRECT NO_OS_BIT(7)
|
||||
|
||||
#define NO_OS_I3C_CCC_ID(id, type) ((id) | (type))
|
||||
|
||||
#define NO_OS_I3C_CCC_ADDR(x) ((x) & 0xFF)
|
||||
#define NO_OS_I3C_CCC_GET_LEN(x) (((x) >> 8) & 0x0000FF)
|
||||
#define NO_OS_I3C_CCC_SET_LEN(x) (((x) << 8) & 0x00FF00)
|
||||
#define NO_OS_I3C_CCC_GET_DEF(x) (((x) >> 17) & NO_OS_BIT(0))
|
||||
#define NO_OS_I3C_CCC_SET_DEF NO_OS_BIT(17)
|
||||
#define NO_OS_I3C_CCC_GET_RNW(x) (((x) >> 16) & NO_OS_BIT(0))
|
||||
#define NO_OS_I3C_CCC_SET_RNW(x) (((x) << 16) & NO_OS_BIT(16))
|
||||
|
||||
/**
|
||||
* Commands valid in both broadcast and direct modes
|
||||
* type: NO_OS_I3C_CCC_DIRECT, NO_OS_I3C_CCC_BCAST
|
||||
*/
|
||||
#define NO_OS_I3C_CCC_ENEC_DIRECT 0x80 | NO_OS_I3C_CCC_SET_LEN(1)
|
||||
#define NO_OS_I3C_CCC_DISEC_DIRECT 0x81 | NO_OS_I3C_CCC_SET_LEN(1)
|
||||
#define NO_OS_I3C_CCC_ENEC_BCAST 0x00 | NO_OS_I3C_CCC_SET_DEF
|
||||
#define NO_OS_I3C_CCC_DISEC_BCAST 0x01 | NO_OS_I3C_CCC_SET_DEF
|
||||
#define NO_OS_I3C_CCC_ENTAS(as, type) NO_OS_I3C_CCC_ID((0x2 + (as)), (type))
|
||||
#define NO_OS_I3C_CCC_RSTDAA(type) NO_OS_I3C_CCC_ID(0x6, (type))
|
||||
#define NO_OS_I3C_CCC_SETMWL(type) NO_OS_I3C_CCC_ID(0x9, (type)) | NO_OS_I3C_CCC_SET_LEN(2)
|
||||
#define NO_OS_I3C_CCC_SETMRL(type) NO_OS_I3C_CCC_ID(0xa, (type)) | NO_OS_I3C_CCC_SET_LEN(2)
|
||||
#define NO_OS_I3C_CCC_SETXTIME_BCAST 0x28 | NO_OS_I3C_CCC_SET_DEF
|
||||
#define NO_OS_I3C_CCC_SETXTIME_DIRECT 0x98 | NO_OS_I3C_CCC_SET_DEF
|
||||
#define NO_OS_I3C_CCC_RSTACT_BCAST 0x2a | NO_OS_I3C_CCC_SET_DEF
|
||||
#define NO_OS_I3C_CCC_RSTACT_DIRECT 0x9a | NO_OS_I3C_CCC_SET_DEF
|
||||
#define NO_OS_I3C_CCC_RSTACT_I3C_ONLY 0x1
|
||||
#define NO_OS_I3C_CCC_RSTACT_WHOLE_TARGET 0x2
|
||||
|
||||
/* Broadcast-only commands */
|
||||
#define NO_OS_I3C_CCC_ENTDAA NO_OS_I3C_CCC_ID(0x7, NO_OS_I3C_CCC_BCAST)
|
||||
#define NO_OS_I3C_CCC_DEFSLVS NO_OS_I3C_CCC_ID(0x8, NO_OS_I3C_CCC_BCAST)
|
||||
#define NO_OS_I3C_CCC_ENTTM NO_OS_I3C_CCC_ID(0xb, NO_OS_I3C_CCC_BCAST)
|
||||
#define NO_OS_I3C_CCC_ENTHDR(x) NO_OS_I3C_CCC_ID((0x20 + (x)), NO_OS_I3C_CCC_BCAST)
|
||||
#define NO_OS_I3C_CCC_SETAASA NO_OS_I3C_CCC_ID(0x29, NO_OS_I3C_CCC_BCAST)
|
||||
|
||||
/* Unicast-only commands */
|
||||
#define NO_OS_I3C_CCC_SETDASA NO_OS_I3C_CCC_ID(0x7, NO_OS_I3C_CCC_DIRECT)
|
||||
#define NO_OS_I3C_CCC_SETNEWDA NO_OS_I3C_CCC_ID(0x8, NO_OS_I3C_CCC_DIRECT)
|
||||
#define NO_OS_I3C_CCC_GETMWL NO_OS_I3C_CCC_ID(0xb, NO_OS_I3C_CCC_DIRECT)
|
||||
#define NO_OS_I3C_CCC_GETMRL NO_OS_I3C_CCC_ID(0xc, NO_OS_I3C_CCC_DIRECT)
|
||||
#define NO_OS_I3C_CCC_GETPID (NO_OS_I3C_CCC_ID(0xd, NO_OS_I3C_CCC_DIRECT) | NO_OS_I3C_CCC_SET_LEN(6) | NO_OS_I3C_CCC_SET_RNW(1))
|
||||
#define NO_OS_I3C_CCC_GETBCR (NO_OS_I3C_CCC_ID(0xe, NO_OS_I3C_CCC_DIRECT) | NO_OS_I3C_CCC_SET_LEN(1) | NO_OS_I3C_CCC_SET_RNW(1))
|
||||
#define NO_OS_I3C_CCC_GETDCR (NO_OS_I3C_CCC_ID(0xf, NO_OS_I3C_CCC_DIRECT) | NO_OS_I3C_CCC_SET_LEN(1) | NO_OS_I3C_CCC_SET_RNW(1))
|
||||
#define NO_OS_I3C_CCC_GETSTATUS (NO_OS_I3C_CCC_ID(0x10, NO_OS_I3C_CCC_DIRECT) | NO_OS_I3C_CCC_SET_LEN(2) | NO_OS_I3C_CCC_SET_RNW(1))
|
||||
#define NO_OS_I3C_CCC_GETACCMST NO_OS_I3C_CCC_ID(0x11, NO_OS_I3C_CCC_DIRECT)
|
||||
#define NO_OS_I3C_CCC_SETBRGTGT NO_OS_I3C_CCC_ID(0x13, NO_OS_I3C_CCC_DIRECT)
|
||||
#define NO_OS_I3C_CCC_GETMXDS NO_OS_I3C_CCC_ID(0x14, NO_OS_I3C_CCC_DIRECT)
|
||||
#define NO_OS_I3C_CCC_GETHDRCAP NO_OS_I3C_CCC_ID(0x15, NO_OS_I3C_CCC_DIRECT)
|
||||
#define NO_OS_I3C_CCC_GETXTIME NO_OS_I3C_CCC_ID(0x19, NO_OS_I3C_CCC_DIRECT)
|
||||
|
||||
#define NO_OS_I3C_CCC_EVENT_SIR NO_OS_BIT(0)
|
||||
#define NO_OS_I3C_CCC_EVENT_MR NO_OS_BIT(1)
|
||||
#define NO_OS_I3C_CCC_EVENT_HJ NO_OS_BIT(3)
|
||||
/**
|
||||
* List of possible IRQ events.
|
||||
*/
|
||||
#define NO_OS_I3C_IRQ_IBI 0x1
|
||||
#define NO_OS_I3C_IRQ_HJ 0x2
|
||||
#define NO_OS_I3C_IRQ_CR 0x4
|
||||
/**
|
||||
* Extract capabilities from BCR
|
||||
*/
|
||||
#define NO_OS_I3C_BCR_IBI_REQUEST_CAPABLE(bcr) !!((bcr) & (1 << 1))
|
||||
#define NO_OS_I3C_BCR_IBI_PAYLOAD(bcr) !!((bcr) & (1 << 2))
|
||||
#define NO_OS_I3C_BCR_DEVICE_ROLE(bcr) (((bcr) && NO_OS_GENMASK(7,6)) >> 6)
|
||||
|
||||
/**
|
||||
* @enum no_os_i3c_slot_status - I3C address slot status
|
||||
*
|
||||
* @brief On an I3C bus, addresses are assigned dynamically, and we need to
|
||||
* know which addresses are free to use and which ones are already assigned.
|
||||
*
|
||||
* Addresses marked as reserved are those reserved by the I3C protocol
|
||||
* (broadcast address, ...).
|
||||
*/
|
||||
enum no_os_i3c_slot_status {
|
||||
/** Address is free */
|
||||
NO_OS_I3C_ADDR_SLOT_FREE,
|
||||
/** Address is reserved */
|
||||
NO_OS_I3C_ADDR_SLOT_RSVD,
|
||||
/** Address is assigned to an I2C device */
|
||||
NO_OS_I3C_ADDR_SLOT_I2C_DEV,
|
||||
/** Address is assigned to an I3C device */
|
||||
NO_OS_I3C_ADDR_SLOT_I3C_DEV,
|
||||
/** Address slot mask */
|
||||
NO_OS_I3C_ADDR_SLOT_STATUS_MASK = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* @union no_os_i3c_ccc_info
|
||||
*/
|
||||
struct no_os_i3c_ccc_info {
|
||||
/** I3C bus receive Target Address during IBI or Bus Role Request event. */
|
||||
uint32_t ibi_cr_addr;
|
||||
/** I3C bus get Number of Data Payload after an IBI event. */
|
||||
uint32_t ibi_payload_len;
|
||||
/** I3C bus received IBI Payload. */
|
||||
uint32_t ibi_payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_i3c_daa_lut
|
||||
* @brief Stores the PID + DA information to look-up during the DAA.
|
||||
* Should be used only for device initialization, since it may
|
||||
* go outdated.
|
||||
*/
|
||||
struct no_os_i3c_daa_lut {
|
||||
bool is_attached;
|
||||
uint8_t addr;
|
||||
uint64_t pid;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_i3c_platform_ops
|
||||
* @brief Structure holding I3C function pointers that point to the platform
|
||||
* specific function.
|
||||
*/
|
||||
struct no_os_i3c_platform_ops;
|
||||
|
||||
/**
|
||||
* @struct no_os_i3c_bus_desc
|
||||
* @brief Structure holding I3C bus descriptor.
|
||||
*/
|
||||
struct no_os_i3c_bus_desc {
|
||||
/** I3C bus mutex(lock)*/
|
||||
void* mutex;
|
||||
/** Device ID*/
|
||||
uint8_t device_id;
|
||||
/** Non-Expected number of devices on bus */
|
||||
uint8_t num_devs_unknown;
|
||||
/** Expected number of devices on bus */
|
||||
uint8_t num_devs;
|
||||
/**
|
||||
* A bitmap with 2-bits per-slot to encode the address status and
|
||||
* ease the DAA (Dynamic Address Assignment) procedure (see
|
||||
* enum ::no_os_i3c_slot_status).
|
||||
*/
|
||||
unsigned int addrslots[NO_OS_I3C_ADDRSLOTS_SIZE];
|
||||
/** PID + DA LUT for DAA procedure */
|
||||
struct no_os_i3c_daa_lut daa_candidates[NO_OS_I3C_MAX_DEV_NUMBER];
|
||||
/** To store unknown devices assigned during DAA procedure */
|
||||
struct no_os_i3c_daa_lut daa_unknown[NO_OS_I3C_MAX_DEV_NUMBER];
|
||||
/** Devices descriptors */
|
||||
struct no_os_i3c_desc *devs[NO_OS_I3C_MAX_DEV_NUMBER];
|
||||
/** IRQ flags */
|
||||
uint8_t irq_events;
|
||||
/** CCC info obtained after an IRQ */
|
||||
struct no_os_i3c_ccc_info ccc_info;
|
||||
/** Trigger IRQ callback asyncronous (non-blocking) */
|
||||
bool async_irq;
|
||||
/** I3C platform specific functions */
|
||||
const struct no_os_i3c_platform_ops *platform_ops;
|
||||
/** I3C bus extra parameters */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_i3c_bus_init_param
|
||||
* @brief Structure holding the parameters for I3C initialization.
|
||||
*/
|
||||
struct no_os_i3c_bus_init_param {
|
||||
/** Device ID */
|
||||
const uint32_t device_id;
|
||||
/** I3C platform specific functions */
|
||||
const struct no_os_i3c_platform_ops *platform_ops;
|
||||
/** Expected number of devices on bus */
|
||||
const uint8_t num_devs;
|
||||
/** Expected devices on bus */
|
||||
const struct no_os_i3c_init_param **devs;
|
||||
/** I3C extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_i3c_init_param
|
||||
* @brief Structure holding the parameters for I3C initialization.
|
||||
* Works like a device tree, the values are copied to no_os_i3c_desc
|
||||
* during I3C initialization.
|
||||
* Set is_static to 1 if the device provides a Static Address and is
|
||||
* desired to use it instead of assigning a Dynamic Address during the
|
||||
* DAA.
|
||||
* is_i3c has higher precedence than is_static, and therefore
|
||||
* is_static does not matter when is_i3c is 0.
|
||||
*/
|
||||
struct no_os_i3c_init_param {
|
||||
/** Pointer to bus init param */
|
||||
struct no_os_i3c_bus_init_param *bus;
|
||||
/** Provisioned ID */
|
||||
uint64_t pid;
|
||||
/** Dynamic or static address */
|
||||
uint8_t addr;
|
||||
/** Is the address static */
|
||||
bool is_static;
|
||||
/** Is I3C or I2C */
|
||||
bool is_i3c;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_i3c_desc
|
||||
* @brief Structure holding I3C device descriptor.
|
||||
*/
|
||||
struct no_os_i3c_desc {
|
||||
/** Provisioned ID */
|
||||
uint64_t pid;
|
||||
/** Dynamic or static address*/
|
||||
uint8_t addr;
|
||||
/** Is I3C or I2C? */
|
||||
bool is_i3c;
|
||||
/** Is attached? */
|
||||
bool is_attached;
|
||||
/** Is the address static? */
|
||||
bool is_static;
|
||||
/** I3C extra parameters (device specific) */
|
||||
void *extra;
|
||||
/** Callback on event*/
|
||||
void (*event_callback)(struct no_os_i3c_desc*, uint32_t, uint32_t);
|
||||
/** I3C platform specific functions */
|
||||
const struct no_os_i3c_platform_ops *platform_ops;
|
||||
/** I3C bus */
|
||||
struct no_os_i3c_bus_desc *bus;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_i3c_platform_ops
|
||||
* @brief Structure holding I3C function pointers that point to the platform
|
||||
* specific function.
|
||||
*/
|
||||
struct no_os_i3c_platform_ops {
|
||||
/** I3C initialization function pointer */
|
||||
int (*i3c_ops_init_bus)(struct no_os_i3c_bus_desc *,
|
||||
const struct no_os_i3c_bus_init_param *);
|
||||
/** I3C initialization function pointer */
|
||||
int (*i3c_ops_init)(struct no_os_i3c_desc *,
|
||||
const struct no_os_i3c_init_param *);
|
||||
/** I3C do daa function pointer */
|
||||
int (*i3c_ops_do_daa)(struct no_os_i3c_bus_desc *, bool);
|
||||
/** I3C send ccc function pointer */
|
||||
int (*i3c_ops_send_ccc)(struct no_os_i3c_bus_desc *, uint8_t, uint8_t,
|
||||
bool, bool, uint8_t *, uint8_t);
|
||||
/** I3C private write function pointer */
|
||||
int (*i3c_ops_write)(struct no_os_i3c_desc *, uint8_t *, uint8_t);
|
||||
/** I3C private read function pointer */
|
||||
int (*i3c_ops_read)(struct no_os_i3c_desc *, uint8_t *, uint8_t);
|
||||
/** I3C private write and read function pointer */
|
||||
int (*i3c_ops_write_and_read)(struct no_os_i3c_desc *, uint8_t *, uint8_t,
|
||||
uint8_t *, uint8_t);
|
||||
/** I3C remove function pointer */
|
||||
int (*i3c_ops_remove_bus)(struct no_os_i3c_bus_desc *);
|
||||
/** I3C remove function pointer */
|
||||
int (*i3c_ops_remove)(struct no_os_i3c_desc *);
|
||||
/** I3C check is device on the bus is ready */
|
||||
int (*i3c_ops_is_dev_ready)(struct no_os_i3c_desc *);
|
||||
/** I3C configure the enabled irq */
|
||||
int (*i3c_ops_conf_irq)(struct no_os_i3c_bus_desc *,
|
||||
uint8_t, bool);
|
||||
/** I3C fetch CCC info */
|
||||
int (*i3c_ops_get_ccc_info)(struct no_os_i3c_bus_desc *,
|
||||
uint8_t);
|
||||
};
|
||||
|
||||
/* Initialize the I3C device. */
|
||||
int no_os_i3c_init(struct no_os_i3c_desc **desc,
|
||||
const struct no_os_i3c_init_param *param);
|
||||
|
||||
/* Initialize the I3C bus. */
|
||||
int no_os_i3c_init_bus(struct no_os_i3c_bus_desc **desc,
|
||||
const struct no_os_i3c_bus_init_param *param);
|
||||
|
||||
/* Free the resources allocated by no_os_i3c_init. */
|
||||
int no_os_i3c_remove(struct no_os_i3c_desc *desc);
|
||||
|
||||
/* Free the resources allocated by no_os_i3c_init_bus + no_os_i3c_init. */
|
||||
int no_os_i3c_remove_bus(struct no_os_i3c_bus_desc *desc);
|
||||
|
||||
/* Do I3C DAA to assign the dynamic addresses. */
|
||||
int no_os_i3c_do_daa(struct no_os_i3c_bus_desc *desc, bool rstdaa);
|
||||
|
||||
/* Send CCC on the bus (direct or broadcast). */
|
||||
int no_os_i3c_send_ccc(struct no_os_i3c_bus_desc *desc,
|
||||
uint8_t addr, uint32_t ccc, uint8_t *data);
|
||||
|
||||
/* Send CCC to a device device. */
|
||||
int no_os_i3c_send_direct_ccc(struct no_os_i3c_desc *desc,
|
||||
uint32_t ccc, uint8_t *data);
|
||||
|
||||
/* Write data to a device device. */
|
||||
int no_os_i3c_write(struct no_os_i3c_desc *desc,
|
||||
uint8_t *data,
|
||||
uint8_t size);
|
||||
|
||||
/* Read data from a device device. */
|
||||
int no_os_i3c_read(struct no_os_i3c_desc *desc,
|
||||
uint8_t *data,
|
||||
uint8_t size);
|
||||
|
||||
/* Write and read data from a device device. */
|
||||
int no_os_i3c_write_and_read(struct no_os_i3c_desc *desc,
|
||||
uint8_t *tx_data,
|
||||
uint8_t tx_data_len,
|
||||
uint8_t *rx_data,
|
||||
uint8_t rx_data_len);
|
||||
|
||||
/* Configure enabled interrupt. */
|
||||
int no_os_i3c_conf_irq(struct no_os_i3c_bus_desc *desc,
|
||||
uint8_t irq, bool en);
|
||||
|
||||
/* Wait I3C interrupt. */
|
||||
int no_os_i3c_wait_irq(struct no_os_i3c_bus_desc* desc,
|
||||
uint8_t irq);
|
||||
|
||||
/* Non-blocking I3C interrupt. */
|
||||
int no_os_i3c_call_irq(struct no_os_i3c_bus_desc* desc);
|
||||
|
||||
/* Enable I3C non-blocking interrupts. */
|
||||
int no_os_i3c_async_irq(struct no_os_i3c_bus_desc *desc, bool en);
|
||||
|
||||
/* Get a free address. */
|
||||
uint8_t no_os_i3c_addr_get_free(struct no_os_i3c_bus_desc *desc,
|
||||
uint8_t start_addr);
|
||||
|
||||
/* Set status of an address. */
|
||||
void no_os_i3c_addr_set_status(struct no_os_i3c_bus_desc *desc,
|
||||
uint8_t addr, enum no_os_i3c_slot_status status);
|
||||
|
||||
/* Attach event callback. */
|
||||
void no_os_i3c_attach_callback(struct no_os_i3c_desc *desc,
|
||||
void (*callback)(struct no_os_i3c_desc*, uint32_t, uint32_t));
|
||||
|
||||
/* Detach event callback. */
|
||||
void no_os_i3c_detach_callback(struct no_os_i3c_desc *desc);
|
||||
|
||||
#endif // _NO_OS_I3C_H_
|
||||
@@ -0,0 +1,38 @@
|
||||
/*******************************************************************************
|
||||
* @file no_os_init.h
|
||||
* @brief Header file of platform initialization.
|
||||
* @author GMois (george.mois@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2022(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_INIT_H_
|
||||
#define _NO_OS_INIT_H_
|
||||
|
||||
int no_os_init(void);
|
||||
|
||||
#endif // _NO_OS_INIT_H_
|
||||
@@ -0,0 +1,265 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_irq.c
|
||||
* @brief Implementation of the IRQ Interface
|
||||
* @author Andrei Porumb (andrei.porumb@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2021(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include "no_os_irq.h"
|
||||
#include "no_os_error.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize the IRQ interrupts.
|
||||
* @param desc - The IRQ descriptor.
|
||||
* @param param - The structure that contains the IRQ parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int no_os_irq_ctrl_init(struct no_os_irq_ctrl_desc **desc,
|
||||
const struct no_os_irq_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!param || !param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->init)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = param->platform_ops->init(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*desc)->ref++;
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by no_os_irq_ctrl_init().
|
||||
* @param desc - The SPI descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int no_os_irq_ctrl_remove(struct no_os_irq_ctrl_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->remove)
|
||||
return -ENOSYS;
|
||||
|
||||
if (--desc->ref)
|
||||
return 0;
|
||||
|
||||
return desc->platform_ops->remove(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register a callback to handle the irq events.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @param callback - Callback descriptor - platform specific type.
|
||||
* @return SUCCESS in case of success, FAILURE otherwise.
|
||||
*/
|
||||
int no_os_irq_register_callback(struct no_os_irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
struct no_os_callback_desc *callback)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->register_callback)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->register_callback(desc, irq_id, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregisters a generic IRQ handling function.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @param callback - Callback descriptor - platform specific type.
|
||||
* @return SUCCESS in case of success, FAILURE otherwise.
|
||||
*/
|
||||
int no_os_irq_unregister_callback(struct no_os_irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
struct no_os_callback_desc *callback)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->unregister_callback)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->unregister_callback(desc, irq_id, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable global interrupts.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int no_os_irq_global_enable(struct no_os_irq_ctrl_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->global_enable)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->global_enable(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable global interrupts.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int no_os_irq_global_disable(struct no_os_irq_ctrl_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->global_disable)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->global_disable(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set interrupt trigger level.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @param trig - New trigger level for the interrupt.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int no_os_irq_trigger_level_set(struct no_os_irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
enum no_os_irq_trig_level trig)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->trigger_level_set)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->trigger_level_set(desc, irq_id, trig);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable specific interrupt.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int no_os_irq_enable(struct no_os_irq_ctrl_desc *desc, uint32_t irq_id)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->enable)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->enable(desc, irq_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable specific interrupt.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int no_os_irq_disable(struct no_os_irq_ctrl_desc *desc, uint32_t irq_id)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->disable)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->disable(desc, irq_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the priority for an interrupt.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @param priority_level - The priority level of the interrupt.
|
||||
* @return 0 in case of success, negative errno error codes.
|
||||
*/
|
||||
int no_os_irq_set_priority(struct no_os_irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
uint32_t priority_level)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->set_priority)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->set_priority(desc, irq_id, priority_level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the priority for an interrupt.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @param priority_level - The priority level of the interrupt.
|
||||
* @return 0 in case of success, negative errno error codes.
|
||||
*/
|
||||
int no_os_irq_get_priority(struct no_os_irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
uint32_t *priority_level)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->get_priority)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->get_priority(desc, irq_id, priority_level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear the pending interrupt.
|
||||
* @param desc - The IRQ controller descriptor.
|
||||
* @param irq_id - Interrupt identifier.
|
||||
* @return 0 in case of success, negative errno error codes.
|
||||
*/
|
||||
int no_os_irq_clear_pending(struct no_os_irq_ctrl_desc* desc,
|
||||
uint32_t irq_id)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->clear_pending)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->clear_pending(desc, irq_id);
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_irq.h
|
||||
* @brief Header file of IRQ interface.
|
||||
* @author Cristian Pop (cristian.pop@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _NO_OS_IRQ_H_
|
||||
#define _NO_OS_IRQ_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @enum no_os_irq_uart_event_e
|
||||
* @brief Possible events for uart interrupt
|
||||
* @todo replace this with enum no_os_irq_event
|
||||
*/
|
||||
enum no_os_irq_uart_event_e {
|
||||
/** Write operation finalized */
|
||||
NO_OS_IRQ_WRITE_DONE,
|
||||
/** Read operation finalized */
|
||||
NO_OS_IRQ_READ_DONE,
|
||||
/** An error occurred */
|
||||
NO_OS_IRQ_ERROR
|
||||
};
|
||||
|
||||
enum no_os_irq_event {
|
||||
NO_OS_EVT_GPIO,
|
||||
NO_OS_EVT_UART_TX_COMPLETE,
|
||||
NO_OS_EVT_UART_RX_COMPLETE,
|
||||
NO_OS_EVT_UART_ERROR,
|
||||
NO_OS_EVT_RTC,
|
||||
NO_OS_EVT_XINT,
|
||||
NO_OS_EVT_TIM_ELAPSED,
|
||||
NO_OS_EVT_TIM_PWM_PULSE_FINISHED,
|
||||
NO_OS_EVT_LPTIM_PWM_PULSE_FINISHED,
|
||||
NO_OS_EVT_DMA_RX_COMPLETE,
|
||||
NO_OS_EVT_DMA_RX_HALF_COMPLETE,
|
||||
NO_OS_EVT_DMA_TX_COMPLETE,
|
||||
NO_OS_EVT_USB,
|
||||
};
|
||||
|
||||
enum no_os_irq_trig_level {
|
||||
NO_OS_IRQ_LEVEL_LOW,
|
||||
NO_OS_IRQ_LEVEL_HIGH,
|
||||
NO_OS_IRQ_EDGE_FALLING,
|
||||
NO_OS_IRQ_EDGE_RISING,
|
||||
NO_OS_IRQ_EDGE_BOTH
|
||||
};
|
||||
|
||||
enum no_os_irq_peripheral {
|
||||
NO_OS_GPIO_IRQ,
|
||||
NO_OS_UART_IRQ,
|
||||
NO_OS_RTC_IRQ,
|
||||
NO_OS_TIM_IRQ,
|
||||
NO_OS_LPTIM_IRQ,
|
||||
NO_OS_TDM_DMA_IRQ,
|
||||
NO_OS_TIM_DMA_IRQ,
|
||||
NO_OS_SPI_DMA_IRQ,
|
||||
NO_OS_DMA_IRQ,
|
||||
NO_OS_USB_IRQ,
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_irq_platform_ops
|
||||
* @brief Structure holding IRQ function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_irq_platform_ops ;
|
||||
|
||||
/**
|
||||
* @struct no_os_irq_init_param
|
||||
* @brief Structure holding the initial parameters for Interrupt Request.
|
||||
*/
|
||||
struct no_os_irq_init_param {
|
||||
/** Interrupt request controller ID. */
|
||||
uint32_t irq_ctrl_id;
|
||||
/** Platform specific IRQ platform ops structure. */
|
||||
const struct no_os_irq_platform_ops *platform_ops;
|
||||
/**
|
||||
* This is intended to store irq controller specific configurations,
|
||||
* it should not be a reference to any peripheral descriptor.
|
||||
*/
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct irq_desc
|
||||
* @brief Structure for Interrupt Request descriptor.
|
||||
*/
|
||||
struct no_os_irq_ctrl_desc {
|
||||
/** Interrupt request controller ID. */
|
||||
uint32_t irq_ctrl_id;
|
||||
/** Platform specific IRQ platform ops structure. */
|
||||
const struct no_os_irq_platform_ops *platform_ops;
|
||||
/* Reference counter */
|
||||
uint32_t ref;
|
||||
/**
|
||||
* This is intended to store irq controller specific configurations,
|
||||
* it should not be a reference to any peripheral descriptor.
|
||||
*/
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_callback_desc
|
||||
* @brief Structure describing a callback to be registered
|
||||
* @todo: remove this, use struct irq_callback instead.
|
||||
*/
|
||||
struct no_os_callback_desc {
|
||||
/** Callback to be called when the event an event occurs. */
|
||||
void (*callback)(void *context);
|
||||
/** Parameter to be passed when the callback is called */
|
||||
void *ctx;
|
||||
/** Platform specific event that triggers the calling of the callback. */
|
||||
enum no_os_irq_event event;
|
||||
/** Interrupt source peripheral specifier. */
|
||||
enum no_os_irq_peripheral peripheral;
|
||||
/** This will be used to store HAL specific descriptors */
|
||||
void *handle;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_irq_platform_ops
|
||||
* @brief Structure holding IRQ function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_irq_platform_ops {
|
||||
/** Initialize a interrupt controller peripheral. */
|
||||
int (*init)(struct no_os_irq_ctrl_desc **desc,
|
||||
const struct no_os_irq_init_param *param);
|
||||
/** Register a callback to handle the irq events */
|
||||
int (*register_callback)(struct no_os_irq_ctrl_desc *desc, uint32_t irq_id,
|
||||
struct no_os_callback_desc *callback);
|
||||
/** Unregisters a generic IRQ handling function */
|
||||
int (*unregister_callback)(struct no_os_irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
struct no_os_callback_desc *callback);
|
||||
/** Global interrupt enable */
|
||||
int (*global_enable)(struct no_os_irq_ctrl_desc *desc);
|
||||
/** Global interrupt disable */
|
||||
int (*global_disable)(struct no_os_irq_ctrl_desc *desc);
|
||||
/** Set interrupt trigger level. */
|
||||
int (*trigger_level_set)(struct no_os_irq_ctrl_desc *desc, uint32_t irq_id,
|
||||
enum no_os_irq_trig_level trig);
|
||||
/** Enable specific interrupt */
|
||||
int (*enable)(struct no_os_irq_ctrl_desc *desc, uint32_t irq_id);
|
||||
/** Disable specific interrupt */
|
||||
int (*disable)(struct no_os_irq_ctrl_desc *desc, uint32_t irq_id);
|
||||
/** Set the priority level for a specific interrupt */
|
||||
int (*set_priority)(struct no_os_irq_ctrl_desc *desc, uint32_t irq_id,
|
||||
uint32_t priority_level);
|
||||
/** Get the priority level for a specific interrupt */
|
||||
int (*get_priority)(struct no_os_irq_ctrl_desc *desc, uint32_t irq_id,
|
||||
uint32_t *priority_level);
|
||||
/** IRQ remove function pointer */
|
||||
int (*remove)(struct no_os_irq_ctrl_desc *desc);
|
||||
/** Clear pending interrupt */
|
||||
int(*clear_pending)(struct no_os_irq_ctrl_desc* desc, uint32_t irq_id);
|
||||
};
|
||||
|
||||
/* Initialize a interrupt controller peripheral. */
|
||||
int no_os_irq_ctrl_init(struct no_os_irq_ctrl_desc **desc,
|
||||
const struct no_os_irq_init_param *param);
|
||||
|
||||
/* Free the resources allocated by no_os_irq_ctrl_init(). */
|
||||
int no_os_irq_ctrl_remove(struct no_os_irq_ctrl_desc *desc);
|
||||
|
||||
/* Register a callback to handle the irq events */
|
||||
int no_os_irq_register_callback(struct no_os_irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
struct no_os_callback_desc *callback_desc);
|
||||
|
||||
/* Unregisters a generic IRQ handling function */
|
||||
int no_os_irq_unregister_callback(struct no_os_irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
struct no_os_callback_desc *callback_desc);
|
||||
|
||||
/* Global interrupt enable */
|
||||
int no_os_irq_global_enable(struct no_os_irq_ctrl_desc *desc);
|
||||
|
||||
/* Global interrupt disable */
|
||||
int no_os_irq_global_disable(struct no_os_irq_ctrl_desc *desc);
|
||||
|
||||
/* Set interrupt trigger level. */
|
||||
int no_os_irq_trigger_level_set(struct no_os_irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
enum no_os_irq_trig_level trig);
|
||||
|
||||
/* Enable specific interrupt */
|
||||
int no_os_irq_enable(struct no_os_irq_ctrl_desc *desc, uint32_t irq_id);
|
||||
|
||||
/* Disable specific interrupt */
|
||||
int no_os_irq_disable(struct no_os_irq_ctrl_desc *desc, uint32_t irq_id);
|
||||
|
||||
/** Set the priority level for a specific interrupt */
|
||||
int no_os_irq_set_priority(struct no_os_irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
uint32_t priority_level);
|
||||
|
||||
/** Get the priority level for a specific interrupt */
|
||||
int no_os_irq_get_priority(struct no_os_irq_ctrl_desc *desc,
|
||||
uint32_t irq_id,
|
||||
uint32_t *priority_level);
|
||||
|
||||
/* Clear the pending interrupts */
|
||||
int no_os_irq_clear_pending(struct no_os_irq_ctrl_desc* desc,
|
||||
uint32_t irq_id);
|
||||
#endif // _NO_OS_IRQ_H_
|
||||
@@ -0,0 +1,148 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_lf256fifo.c
|
||||
* @brief SPSC lock-free fifo of fixed size (256), specialized for UART.
|
||||
* @author Darius Berghe (darius.berghe@analog.com)
|
||||
********************************************************************************
|
||||
* @copyright
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#include <errno.h>
|
||||
#include "no_os_lf256fifo.h"
|
||||
#include "no_os_alloc.h"
|
||||
|
||||
/**
|
||||
* @struct lf256fifo
|
||||
* @brief Structure holding the fifo element parameters.
|
||||
*/
|
||||
struct lf256fifo {
|
||||
uint8_t * data; // pointer to memory area where the buffer will be allocated
|
||||
uint8_t ffilled; // the index where the data starts
|
||||
uint8_t fempty; // the index where empty/non-used area starts
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initialize and allocate a lock-free 256 FIFO.
|
||||
* @param fifo - pointer to a fifo descriptor pointer.
|
||||
* @return 0 if successful, negative error code otherwise.
|
||||
*/
|
||||
int lf256fifo_init(struct lf256fifo **fifo)
|
||||
{
|
||||
if (fifo == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
struct lf256fifo *b = no_os_calloc(1, sizeof(struct lf256fifo));
|
||||
if (b == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
b->data = no_os_calloc(1, 256);
|
||||
if (b->data == NULL) {
|
||||
no_os_free(b);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*fifo = b;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test whether fifo is full.
|
||||
* @param fifo - pointer to fifo descriptor.
|
||||
* @return true if fifo is full, false if not full.
|
||||
*/
|
||||
bool lf256fifo_is_full(struct lf256fifo *fifo)
|
||||
{
|
||||
return (fifo->fempty + 1) ==
|
||||
fifo->ffilled; // intended overflow at 256 (data size is 256)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test whether fifo is empty.
|
||||
* @param fifo - pointer to fifo descriptor.
|
||||
* @return true if fifo is empty, false if not empty.
|
||||
*/
|
||||
bool lf256fifo_is_empty(struct lf256fifo *fifo)
|
||||
{
|
||||
return fifo->fempty == fifo->ffilled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read char from fifo.
|
||||
* @param fifo - pointer to fifo descriptor.
|
||||
* @param c - pointer to memory where the char element is read.
|
||||
* @return 0 if successful, -1 if buffer empty.
|
||||
*/
|
||||
int lf256fifo_read(struct lf256fifo * fifo, uint8_t *c)
|
||||
{
|
||||
if (lf256fifo_is_empty(fifo))
|
||||
return -1; // buffer empty
|
||||
|
||||
*c = fifo->data[fifo->ffilled];
|
||||
fifo->ffilled++; // intended overflow at 256 (data size is 256)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write char to fifo.
|
||||
* @param fifo - pointer to fifo descriptor.
|
||||
* @param c - char element to write.
|
||||
* @return 0 if successful, -1 if buffer full.
|
||||
*/
|
||||
int lf256fifo_write(struct lf256fifo *fifo, uint8_t c)
|
||||
{
|
||||
if (lf256fifo_is_full(fifo))
|
||||
return -1; // buffer full
|
||||
|
||||
fifo->data[fifo->fempty] = c;
|
||||
fifo->fempty++; // intended overflow at 256 (data size is 256)
|
||||
|
||||
return 0; // return success
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Flush the fifo.
|
||||
* @param fifo - pointer to fifo descriptor.
|
||||
* @return void
|
||||
*/
|
||||
void lf256fifo_flush(struct lf256fifo *fifo)
|
||||
{
|
||||
fifo->ffilled = fifo->fempty;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove the fifo
|
||||
* @param fifo - pointer to fifo descriptor.
|
||||
* @return void
|
||||
*/
|
||||
void lf256fifo_remove(struct lf256fifo *fifo)
|
||||
{
|
||||
if (fifo && fifo->data)
|
||||
no_os_free(fifo->data);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_lf256fifo.h
|
||||
* @brief SPSC lock-free fifo of fixed size (256), specialized for UART.
|
||||
* @author Darius Berghe (darius.berghe@analog.com)
|
||||
********************************************************************************
|
||||
* @copyright
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __LFFIFO_H
|
||||
#define __LFFIFO_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct lf256fifo;
|
||||
|
||||
int lf256fifo_init(struct lf256fifo **);
|
||||
bool lf256fifo_is_full(struct lf256fifo *);
|
||||
bool lf256fifo_is_empty(struct lf256fifo *);
|
||||
int lf256fifo_read(struct lf256fifo *, uint8_t *);
|
||||
int lf256fifo_write(struct lf256fifo *, uint8_t);
|
||||
void lf256fifo_flush(struct lf256fifo *);
|
||||
void lf256fifo_remove(struct lf256fifo *fifo);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,871 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_list.c
|
||||
* @brief List library implementation
|
||||
* @author Mihail Chindris (mihail.chindris@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "no_os_list.h"
|
||||
#include "no_os_error.h"
|
||||
#include "no_os_alloc.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* @struct no_os_list_elem
|
||||
* @brief Format of each element of the list
|
||||
*/
|
||||
struct no_os_list_elem {
|
||||
/** User data */
|
||||
void *data;
|
||||
/** Reference to previous element */
|
||||
struct no_os_list_elem *prev;
|
||||
/** Reference to next element */
|
||||
struct no_os_list_elem *next;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct list_iterator
|
||||
* @brief Structure used to iterate through the list
|
||||
*/
|
||||
struct no_os_iterator {
|
||||
/** List reference */
|
||||
struct _list_desc *list;
|
||||
/** Current element reference */
|
||||
struct no_os_list_elem *elem;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct _list_desc
|
||||
* @brief List descriptor
|
||||
*/
|
||||
struct _list_desc {
|
||||
/** Reference to first element in the list */
|
||||
struct no_os_list_elem *first;
|
||||
/** Reference to last element in the list*/
|
||||
struct no_os_list_elem *last;
|
||||
/** Number of elements in the list */
|
||||
uint32_t nb_elements;
|
||||
/** Function used to compare elements */
|
||||
f_cmp comparator;
|
||||
/** Number of current active iterators */
|
||||
uint32_t nb_iterators;
|
||||
/** Internal list iterator */
|
||||
struct no_os_iterator l_it;
|
||||
};
|
||||
|
||||
/** @brief Default function used to compare element in the list ( \ref f_cmp) */
|
||||
static int32_t no_os_default_comparator(void *data1, void *data2)
|
||||
{
|
||||
return (int32_t)((int32_t *)data1 - (int32_t *)data2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a new list elements an configure its value
|
||||
* @param data - To set list_elem.data
|
||||
* @param prev - To set list_elem.prev
|
||||
* @param next - To set list_elem.next
|
||||
* @return Address of the new element or NULL if allocation fails.
|
||||
*/
|
||||
static inline struct no_os_list_elem *create_element(void *data,
|
||||
struct no_os_list_elem *prev,
|
||||
struct no_os_list_elem *next)
|
||||
{
|
||||
struct no_os_list_elem *elem;
|
||||
|
||||
elem = (struct no_os_list_elem *)no_os_calloc(1, sizeof(*elem));
|
||||
if (!elem)
|
||||
return NULL;
|
||||
elem->data = data;
|
||||
elem->prev = prev;
|
||||
elem->next = next;
|
||||
|
||||
return (elem);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates the necesary link on the list elements to add or remove one
|
||||
* @param prev - Low element
|
||||
* @param elem - Middle element
|
||||
* @param next - High element
|
||||
*/
|
||||
static inline void no_os_update_links(struct no_os_list_elem *prev,
|
||||
struct no_os_list_elem *elem,
|
||||
struct no_os_list_elem *next)
|
||||
{
|
||||
if (prev)
|
||||
prev->next = elem ? elem : next;
|
||||
if (elem) {
|
||||
elem->prev = prev;
|
||||
elem->next = next;
|
||||
}
|
||||
if (next)
|
||||
next->prev = elem ? elem : prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update according to modification the list descriptor
|
||||
* @param list - List reference
|
||||
* @param new_first - New first element
|
||||
* @param new_last - New last element
|
||||
*/
|
||||
static inline void no_os_update_desc(struct _list_desc *list,
|
||||
struct no_os_list_elem *new_first,
|
||||
struct no_os_list_elem *new_last)
|
||||
{
|
||||
if (new_first == list->first) {
|
||||
list->last = new_last;
|
||||
if (new_first == NULL || new_last == NULL)
|
||||
list->first = new_last;
|
||||
} else { /* if (new_last == list->last) */
|
||||
list->first = new_first;
|
||||
if (new_last == NULL || new_first == NULL)
|
||||
list->last = new_first;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the adapter functions acording to the adapter type
|
||||
* @param ad - Reference of the adapter
|
||||
* @param type - Type of the adapter
|
||||
*/
|
||||
static inline void no_os_set_adapter(struct no_os_list_desc *ad,
|
||||
enum no_os_adapter_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case NO_OS_LIST_PRIORITY_LIST:
|
||||
ad->push = no_os_list_add_find;
|
||||
ad->pop = no_os_list_get_first;
|
||||
ad->top_next = no_os_list_read_first;
|
||||
ad->back = no_os_list_read_last;
|
||||
ad->swap = no_os_list_edit_first;
|
||||
break;
|
||||
case NO_OS_LIST_QUEUE:
|
||||
ad->push = no_os_list_add_last;
|
||||
ad->pop = no_os_list_get_first;
|
||||
ad->top_next = no_os_list_read_first;
|
||||
ad->back = no_os_list_read_last;
|
||||
ad->swap = no_os_list_edit_first;
|
||||
break;
|
||||
case NO_OS_LIST_DEFAULT:
|
||||
case NO_OS_LIST_STACK:
|
||||
default:
|
||||
ad->push = no_os_list_add_last;
|
||||
ad->pop = no_os_list_get_last;
|
||||
ad->top_next = no_os_list_read_last;
|
||||
ad->back = no_os_list_read_first;
|
||||
ad->swap = no_os_list_edit_last;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a new empty list
|
||||
* @param list_desc - Where to store the reference of the new created list
|
||||
* @param type - Type of adapter to use.
|
||||
* @param comparator - Used to compare item when using an ordered list or when
|
||||
* using the \em find functions.
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
*/
|
||||
int32_t no_os_list_init(struct no_os_list_desc **list_desc,
|
||||
enum no_os_adapter_type type,
|
||||
f_cmp comparator)
|
||||
{
|
||||
struct no_os_list_desc *l_desc;
|
||||
struct _list_desc *list;
|
||||
|
||||
|
||||
if (!list_desc)
|
||||
return -1;
|
||||
l_desc = (struct no_os_list_desc *)no_os_calloc(1, sizeof(*l_desc));
|
||||
if (!l_desc)
|
||||
return -1;
|
||||
list = (struct _list_desc *)no_os_calloc(1, sizeof(*list));
|
||||
if (!list) {
|
||||
no_os_free(l_desc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*list_desc = l_desc;
|
||||
l_desc->priv_desc = list;
|
||||
list->comparator = comparator ? comparator : no_os_default_comparator;
|
||||
|
||||
/* Configure wrapper */
|
||||
no_os_set_adapter(l_desc, type);
|
||||
list->l_it.list = list;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove the created list.
|
||||
*
|
||||
* All its elements will be cleared and the data inside each will be lost. If
|
||||
* not all iterators have been removed, the list will not be removed.
|
||||
* @param list_desc - Reference to the list
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
*/
|
||||
int32_t no_os_list_remove(struct no_os_list_desc *list_desc)
|
||||
{
|
||||
void *data;
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc)
|
||||
return -1;
|
||||
|
||||
list = list_desc->priv_desc;
|
||||
if (list->nb_iterators != 0)
|
||||
return -1;
|
||||
|
||||
/* Remove all the elements */
|
||||
while (0 == no_os_list_get_first(list_desc, &data))
|
||||
;
|
||||
no_os_free(list_desc->priv_desc);
|
||||
no_os_free(list_desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the number of elements inside the list
|
||||
* @param list_desc - List reference
|
||||
* @param out_size - Where to store the number of elements
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
*/
|
||||
int32_t no_os_list_get_size(struct no_os_list_desc *list_desc,
|
||||
uint32_t *out_size)
|
||||
{
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc || !out_size)
|
||||
return -1;
|
||||
|
||||
list = list_desc->priv_desc;
|
||||
*out_size = list->nb_elements;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Add element at the begining of the list. Refer to \ref f_add */
|
||||
int32_t no_os_list_add_first(struct no_os_list_desc *list_desc, void *data)
|
||||
{
|
||||
struct no_os_list_elem *prev;
|
||||
struct no_os_list_elem *next;
|
||||
struct no_os_list_elem *elem;
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc)
|
||||
return -1;
|
||||
|
||||
list = list_desc->priv_desc;
|
||||
|
||||
prev = NULL;
|
||||
next = list->first;
|
||||
elem = create_element(data, prev, next);
|
||||
if (!elem)
|
||||
return -1;
|
||||
|
||||
no_os_update_links(prev, elem, next);
|
||||
|
||||
no_os_update_desc(list, elem, list->last);
|
||||
|
||||
list->nb_elements++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Add element at the end of the list. Refer to \ref f_add */
|
||||
int32_t no_os_list_add_last(struct no_os_list_desc *list_desc, void *data)
|
||||
{
|
||||
struct no_os_list_elem *prev;
|
||||
struct no_os_list_elem *next;
|
||||
struct no_os_list_elem *elem;
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc)
|
||||
return -1;
|
||||
list = list_desc->priv_desc;
|
||||
|
||||
prev = list->last;
|
||||
next = NULL;
|
||||
elem = create_element(data, prev, next);
|
||||
if (!elem)
|
||||
return -1;
|
||||
|
||||
no_os_update_links(prev, elem, next);
|
||||
|
||||
no_os_update_desc(list, list->first, elem);
|
||||
|
||||
list->nb_elements++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Add element at the specified idx. Refer to \ref f_add */
|
||||
int32_t no_os_list_add_idx(struct no_os_list_desc *list_desc, void *data,
|
||||
uint32_t idx)
|
||||
{
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc)
|
||||
return -1;
|
||||
list = list_desc->priv_desc;
|
||||
|
||||
/* If there are no elements the creation of an iterator will fail */
|
||||
if (list->nb_elements == 0 || idx == 0)
|
||||
return no_os_list_add_first(list_desc, data);
|
||||
if (list->nb_elements == idx)
|
||||
return no_os_list_add_last(list_desc, data);
|
||||
|
||||
list->l_it.elem = list->first;
|
||||
if (0 != no_os_iterator_move(&(list->l_it), idx))
|
||||
return -1;
|
||||
|
||||
return no_os_iterator_insert(&(list->l_it), data, 0);
|
||||
}
|
||||
|
||||
/** @brief Add element in ascending order. Refer to \ref f_add */
|
||||
int32_t no_os_list_add_find(struct no_os_list_desc *list_desc, void *data)
|
||||
{
|
||||
struct no_os_list_elem *elem;
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc)
|
||||
return -1;
|
||||
list = list_desc->priv_desc;
|
||||
|
||||
|
||||
/* Based on place iterator */
|
||||
elem = list->first;
|
||||
while (elem) {
|
||||
if (0 < list->comparator(elem->data, data))
|
||||
break;
|
||||
elem = elem->next;
|
||||
}
|
||||
if (elem == NULL) {
|
||||
list->l_it.elem = list->last;
|
||||
return no_os_iterator_insert(&(list->l_it), data, 1);
|
||||
} else {
|
||||
list->l_it.elem = elem;
|
||||
return no_os_iterator_insert(&(list->l_it), data, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** @brief Edit the first element of the list. Refer to \ref f_edit */
|
||||
int32_t no_os_list_edit_first(struct no_os_list_desc *list_desc, void *new_data)
|
||||
{
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc)
|
||||
return -1;
|
||||
|
||||
list = list_desc->priv_desc;
|
||||
list->first->data = new_data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Edit the last element of the list. Refer to \ref f_edit */
|
||||
int32_t no_os_list_edit_last(struct no_os_list_desc *list_desc, void *new_data)
|
||||
{
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc)
|
||||
return -1;
|
||||
|
||||
list = list_desc->priv_desc;
|
||||
list->last->data = new_data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Edit the element at the specified idx. Refer to \ref f_edit */
|
||||
int32_t no_os_list_edit_idx(struct no_os_list_desc *list_desc, void *new_data,
|
||||
uint32_t idx)
|
||||
{
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc)
|
||||
return -1;
|
||||
list = list_desc->priv_desc;
|
||||
|
||||
list->l_it.elem = list->first;
|
||||
if (0 != no_os_iterator_move(&(list->l_it), idx))
|
||||
return -1;
|
||||
|
||||
return no_os_iterator_edit(&(list->l_it), new_data);
|
||||
}
|
||||
|
||||
/** @brief Edit the element which match with cmp_data. Refer to \ref f_edit */
|
||||
int32_t no_os_list_edit_find(struct no_os_list_desc *list_desc, void *new_data,
|
||||
void *cmp_data)
|
||||
{
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc)
|
||||
return -1;
|
||||
list = list_desc->priv_desc;
|
||||
|
||||
list->l_it.elem = list->first;
|
||||
if (0 != no_os_iterator_find(&(list->l_it), cmp_data))
|
||||
return -1;
|
||||
|
||||
return no_os_iterator_edit(&(list->l_it), new_data);
|
||||
}
|
||||
|
||||
/** @brief Read the first element of the list. Refer to \ref f_read */
|
||||
int32_t no_os_list_read_first(struct no_os_list_desc *list_desc, void **data)
|
||||
{
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc || !data)
|
||||
return -1;
|
||||
|
||||
*data = NULL;
|
||||
list = list_desc->priv_desc;
|
||||
if (!list->first)
|
||||
return -1;
|
||||
|
||||
*data = list->first->data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Read the last element of the list. Refer to \ref f_read */
|
||||
int32_t no_os_list_read_last(struct no_os_list_desc *list_desc, void **data)
|
||||
{
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc || !data)
|
||||
return -1;
|
||||
|
||||
*data = NULL;
|
||||
list = list_desc->priv_desc;
|
||||
if (!list->last)
|
||||
return -1;
|
||||
|
||||
*data = list->last->data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Read the element at the specified idx. Refer to \ref f_read */
|
||||
int32_t no_os_list_read_idx(struct no_os_list_desc *list_desc, void **data,
|
||||
uint32_t idx)
|
||||
{
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc || !data)
|
||||
return -1;
|
||||
|
||||
*data = NULL;
|
||||
list = list_desc->priv_desc;
|
||||
if (!list)
|
||||
return -1;
|
||||
|
||||
if (idx >= list->nb_elements)
|
||||
return -1;
|
||||
|
||||
list->l_it.elem = list->first;
|
||||
if (0 != no_os_iterator_move(&(list->l_it), idx))
|
||||
return -1;
|
||||
|
||||
return no_os_iterator_read(&(list->l_it), data);
|
||||
}
|
||||
|
||||
/** @brief Read the element which match with cmp_data. Refer to \ref f_read */
|
||||
int32_t no_os_list_read_find(struct no_os_list_desc *list_desc, void **data,
|
||||
void *cmp_data)
|
||||
{
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc || !data)
|
||||
return -1;
|
||||
|
||||
*data = NULL;
|
||||
list = list_desc->priv_desc;
|
||||
if (!list)
|
||||
return -1;
|
||||
|
||||
list = list_desc->priv_desc;
|
||||
list->l_it.elem = list->first;
|
||||
if (0 != no_os_iterator_find(&(list->l_it), cmp_data))
|
||||
return -1;
|
||||
|
||||
return no_os_iterator_read(&(list->l_it), data);
|
||||
}
|
||||
|
||||
/** @brief Read and delete the first element of the list. Refer to \ref f_get */
|
||||
int32_t no_os_list_get_first(struct no_os_list_desc *list_desc, void **data)
|
||||
{
|
||||
struct no_os_list_elem *prev;
|
||||
struct no_os_list_elem *next;
|
||||
struct no_os_list_elem *elem;
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc || !data)
|
||||
return -1;
|
||||
|
||||
*data = NULL;
|
||||
list = list_desc->priv_desc;
|
||||
if (!list->nb_elements)
|
||||
return -1;
|
||||
|
||||
elem = list->first;
|
||||
prev = elem->prev;
|
||||
next = elem->next;
|
||||
|
||||
no_os_update_links(prev, NULL, next);
|
||||
no_os_update_desc(list, next, list->last);
|
||||
list->nb_elements--;
|
||||
|
||||
*data = elem->data;
|
||||
no_os_free(elem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Read and delete the last element of the list. Refer to \ref f_get */
|
||||
int32_t no_os_list_get_last(struct no_os_list_desc *list_desc, void **data)
|
||||
{
|
||||
struct no_os_list_elem *prev;
|
||||
struct no_os_list_elem *next;
|
||||
struct no_os_list_elem *elem;
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc || !data)
|
||||
return -1;
|
||||
|
||||
*data = NULL;
|
||||
list = list_desc->priv_desc;
|
||||
if (!list->nb_elements)
|
||||
return -1;
|
||||
|
||||
elem = list->last;
|
||||
prev = elem->prev;
|
||||
next = elem->next;
|
||||
|
||||
no_os_update_links(prev, NULL, next);
|
||||
no_os_update_desc(list, list->first, prev);
|
||||
list->nb_elements--;
|
||||
|
||||
*data = elem->data;
|
||||
no_os_free(elem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Read and delete the element at idx. Refer to \ref f_get */
|
||||
int32_t no_os_list_get_idx(struct no_os_list_desc *list_desc, void **data,
|
||||
uint32_t idx)
|
||||
{
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc || !data)
|
||||
return -1;
|
||||
|
||||
*data = NULL;
|
||||
list = list_desc->priv_desc;
|
||||
list->l_it.elem = list->first;
|
||||
if (0 != no_os_iterator_move(&(list->l_it), idx))
|
||||
return -1;
|
||||
|
||||
return no_os_iterator_get(&(list->l_it), data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read and delete the element which match with cmp_data.
|
||||
* Refer to \ref f_get
|
||||
*/
|
||||
int32_t no_os_list_get_find(struct no_os_list_desc *list_desc, void **data,
|
||||
void *cmp_data)
|
||||
{
|
||||
struct _list_desc *list;
|
||||
|
||||
if (!list_desc || !data)
|
||||
return -1;
|
||||
|
||||
*data = NULL;
|
||||
list = list_desc->priv_desc;
|
||||
list->l_it.elem = list->first;
|
||||
if (0 != no_os_iterator_find(&(list->l_it), cmp_data))
|
||||
return -1;
|
||||
|
||||
return no_os_iterator_get(&(list->l_it), data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a new iterator
|
||||
* @param iter - Where to store the reference for the new iterator
|
||||
* @param list_desc - Reference of the list the iterator will be used for
|
||||
* @param start - If it is true the iterator will be positioned at the first
|
||||
* element of the list, else it will be positioned at the last.
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
*/
|
||||
int32_t no_os_iterator_init(struct no_os_iterator **iter,
|
||||
struct no_os_list_desc *list_desc,
|
||||
bool start)
|
||||
{
|
||||
struct no_os_iterator *it;
|
||||
|
||||
if (!list_desc)
|
||||
return -1;
|
||||
|
||||
it = (struct no_os_iterator *)no_os_calloc(1, sizeof(*it));
|
||||
if (!it)
|
||||
return -1;
|
||||
it->list = list_desc->priv_desc;
|
||||
it->list->nb_iterators++;
|
||||
it->elem = start ? it->list->first : it->list->last;
|
||||
*iter = it;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove the created iterator
|
||||
* @param iter - Reference of the iterator
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
*/
|
||||
int32_t no_os_iterator_remove(struct no_os_iterator *iter)
|
||||
{
|
||||
struct no_os_iterator *it = iter;
|
||||
|
||||
if (!it)
|
||||
return -1;
|
||||
|
||||
it->list->nb_iterators--;
|
||||
no_os_free(it);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move the position of the iteration through the list.
|
||||
*
|
||||
* If the required position is outside the list, the call will fail and the
|
||||
* iterator will keep its position.
|
||||
* @param iter - Reference of the iterator
|
||||
* @param steps - Number of positions to be move. If positive, it will be moved
|
||||
* forward, otherwise backwords.
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
*/
|
||||
int32_t no_os_iterator_move(struct no_os_iterator *iter, int32_t steps)
|
||||
{
|
||||
struct no_os_iterator *it = iter;
|
||||
struct no_os_list_elem *elem;
|
||||
int32_t dir = (steps < 0) ? -1 : 1;
|
||||
|
||||
if (!it)
|
||||
return -1;
|
||||
|
||||
steps = abs(steps);
|
||||
elem = it->elem;
|
||||
while (steps > 0 && elem) {
|
||||
elem = dir > 0 ? elem->next : elem->prev;
|
||||
steps--;
|
||||
}
|
||||
if (!elem)
|
||||
return -1;
|
||||
|
||||
it->elem = elem;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move the position of the iterator at the specified index of the list.
|
||||
*
|
||||
* @param iter - Reference of the iterator
|
||||
* @param idx - Position in the list. If negative start counting backwords
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
*/
|
||||
int32_t no_os_iterator_move_to_idx(struct no_os_iterator *iter, int32_t idx)
|
||||
{
|
||||
struct no_os_list_elem *elem;
|
||||
int32_t dir = (idx < 0) ? -1 : 1;
|
||||
|
||||
if (!iter)
|
||||
return -1;
|
||||
|
||||
idx = abs(idx);
|
||||
elem = dir > 0 ? iter->list->first : iter->list->last;
|
||||
while (idx > 0 && elem) {
|
||||
elem = dir > 0 ? elem->next : elem->prev;
|
||||
idx--;
|
||||
}
|
||||
if (!elem)
|
||||
return -1;
|
||||
|
||||
iter->elem = elem;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Place the iterator where cmp_data if found.
|
||||
* @param iter - Reference to the iterator
|
||||
* @param cmp_data - Data to be found
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
*/
|
||||
int32_t no_os_iterator_find(struct no_os_iterator *iter, void *cmp_data)
|
||||
{
|
||||
struct no_os_iterator *it = iter;
|
||||
struct no_os_list_elem *elem;
|
||||
|
||||
if (!it)
|
||||
return -1;
|
||||
|
||||
elem = it->list->first;
|
||||
while (elem) {
|
||||
if (0 == it->list->comparator(elem->data, cmp_data)) {
|
||||
it->elem = elem;
|
||||
return 0;
|
||||
}
|
||||
elem = elem->next;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Replace the data at the current position. Refer to \ref f_edit
|
||||
*/
|
||||
int32_t no_os_iterator_edit(struct no_os_iterator *iter, void *new_data)
|
||||
{
|
||||
struct no_os_iterator *it = iter;
|
||||
|
||||
if (!it)
|
||||
return -1;
|
||||
|
||||
it->elem->data = new_data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read and remove the data at the current position. Refer to \ref f_get.
|
||||
*
|
||||
* If the current item is the last one, the iterator will be moved to the
|
||||
* previous one.
|
||||
*/
|
||||
int32_t no_os_iterator_get(struct no_os_iterator *iter, void **data)
|
||||
{
|
||||
struct no_os_iterator *it = iter;
|
||||
struct no_os_list_elem *next;
|
||||
|
||||
|
||||
if (!it || !it->elem || !data)
|
||||
return -1;
|
||||
|
||||
no_os_update_links(it->elem->prev, NULL, it->elem->next);
|
||||
if (it->elem == it->list->first)
|
||||
no_os_update_desc(it->list, it->elem->next, it->list->last);
|
||||
else if (it->elem == it->list->last)
|
||||
no_os_update_desc(it->list, it->list->first, it->elem->prev);
|
||||
it->list->nb_elements--;
|
||||
|
||||
*data = it->elem->data;
|
||||
if (it->elem == it->list->last)
|
||||
next = it->elem->prev;
|
||||
else
|
||||
next = it->elem->next;
|
||||
no_os_free(it->elem);
|
||||
it->elem = next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read the data at the current position. Refer to \ref f_read
|
||||
*/
|
||||
int32_t no_os_iterator_read(struct no_os_iterator *iter, void **data)
|
||||
{
|
||||
struct no_os_iterator *it = iter;
|
||||
|
||||
if (!it || !it->elem || !data)
|
||||
return -1;
|
||||
|
||||
*data = it->elem->data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert an item in the list. Refer to \ref f_add
|
||||
* @param iter
|
||||
* @param data
|
||||
* @param after - If true, the item will be inserted after the current position.
|
||||
* Otherwise it will be inserted before.
|
||||
*/
|
||||
int32_t no_os_iterator_insert(struct no_os_iterator *iter, void *data,
|
||||
bool after)
|
||||
{
|
||||
struct no_os_iterator *it = iter;
|
||||
struct no_os_list_elem *elem;
|
||||
struct no_os_list_desc list_desc;
|
||||
|
||||
if (!it)
|
||||
return -1;
|
||||
|
||||
list_desc.priv_desc = iter->list;
|
||||
if (after && it->elem == it->list->last)
|
||||
return no_os_list_add_last(&list_desc, data);
|
||||
if (!after && it->elem == it->list->first)
|
||||
return no_os_list_add_first(&list_desc, data);
|
||||
|
||||
if (after)
|
||||
elem = create_element(data, it->elem, it->elem->next);
|
||||
else
|
||||
elem = create_element(data, it->elem->prev, it->elem);
|
||||
if (!elem)
|
||||
return -1;
|
||||
|
||||
no_os_update_links(elem->prev, elem, elem->next);
|
||||
|
||||
it->list->nb_elements++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_list.h
|
||||
* @brief List library header
|
||||
* @author Mihail Chindris (mihail.chindris@analog.com)
|
||||
********************************************************************************
|
||||
* @copyright
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
********************************************************************************
|
||||
*
|
||||
* @section list_details Library description
|
||||
* This library handles double linked lists and it expose inseart,
|
||||
* read, get and delete functions. \n
|
||||
* It also can be accesed using it member functions which wrapp function for
|
||||
* usual list types.\n
|
||||
* @subsection example Sample code
|
||||
* @code{.c}
|
||||
* // -- Use a generic list
|
||||
* struct no_os_list_desc *list1;
|
||||
* struct no_os_iterator *it;
|
||||
* uint32_t a;
|
||||
* // Create list list1
|
||||
* no_os_list_init(&list1, NO_OS_LIST_DEFAULT, NULL);
|
||||
* // Add items to the list
|
||||
* no_os_list_add_last(list1, 1);
|
||||
* no_os_list_add_last(list1, 2);
|
||||
* no_os_list_add_last(list1, 3);
|
||||
* // Here the list will be: 1 -> 2 - > 3
|
||||
*
|
||||
* no_os_list_read_last(list1, &a);
|
||||
* printf("Last: %d\n", a);
|
||||
* // 3 will be printed
|
||||
* // Create an iterator on the end of the list
|
||||
* no_os_iterator_init(&it, list1, 0);
|
||||
* // Move the iterator backword with one position
|
||||
* no_os_iterator_move(it, -1);
|
||||
* // Read the data at the current position
|
||||
* no_os_iterator_read(it, &a);
|
||||
* printf("Current: %d\n", a);
|
||||
* // 2 will be printed
|
||||
* no_os_iterator_remove(it);
|
||||
* no_os_list_remove(list1);
|
||||
*
|
||||
* // -- Use a popular list
|
||||
* struct no_os_list_desc *stack;
|
||||
* // Create a FIFO list
|
||||
* no_os_list_init(&stack, NO_OS_LIST_STACK, NULL);
|
||||
* // Put elements in the list
|
||||
* stack->push(stack, 1);
|
||||
* stack->push(stack, 2);
|
||||
* stack->push(stack, 3);
|
||||
* // Read from the stack
|
||||
* stack->pop(stack, &a);
|
||||
* printf("Last: %d\n", a);
|
||||
* // 3 will be printed
|
||||
* no_os_list_remove(stack);
|
||||
* @endcode
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _NO_OS_LIST_H_
|
||||
#define _NO_OS_LIST_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* @struct no_os_list_desc
|
||||
* @brief Structure storing the list and function wrapper for usual list types
|
||||
*
|
||||
* With this structure the funtionalities of usual list types
|
||||
* ( \ref no_os_adapter_type ) can be accesed with the functions referenced in this
|
||||
* structure.
|
||||
* For example:
|
||||
* @code{.c}
|
||||
* my_queue->push(my_queue, my_data);
|
||||
* @endcode
|
||||
*/
|
||||
struct no_os_list_desc;
|
||||
|
||||
/**
|
||||
* @struct list_iterator
|
||||
* @brief Structure used to iterate through the list using Iterator functions.
|
||||
*/
|
||||
struct no_os_iterator;
|
||||
|
||||
/**
|
||||
* @brief Prototype of the compare function.
|
||||
*
|
||||
* The function used to compare the elements of the liste when doing
|
||||
* operations on an ordered list.
|
||||
* @param data1 - First element to be compared
|
||||
* @param data2 - Second element to be compared
|
||||
* @return
|
||||
* - -1 - If data1 < data2
|
||||
* - 0 - If data1 == data2
|
||||
* - 1 - If data1 > data2
|
||||
*/
|
||||
typedef int32_t (*f_cmp)(void *data1, void *data2);
|
||||
|
||||
/**
|
||||
* @name Generic functions
|
||||
* Each function interacting with the list have one of the following formats.\n
|
||||
* Aditionaly they may have one more parametere for specific functionalities.\n
|
||||
* In the Iterator functions, the list reference is replaced by the iterator's
|
||||
* one.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Add an element in the list.
|
||||
*
|
||||
* The element of the list is created and the data field is stored in it.
|
||||
* @param list_desc - Reference to the list. Created by \ref no_os_list_init.
|
||||
* @param data - Data to store in a list element
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
*/
|
||||
typedef int32_t (*f_add)(struct no_os_list_desc *list_desc, void *data);
|
||||
|
||||
/**
|
||||
* @brief Edit an element in the list. The content is replaced by new_data.
|
||||
* @param list_desc - Reference to the list. Created by \ref no_os_list_init.
|
||||
* @param new_data - New data to replace the old one
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
*/
|
||||
typedef int32_t (*f_edit)(struct no_os_list_desc *list_desc, void *new_data);
|
||||
|
||||
/**
|
||||
* @brief Read an element from the list.
|
||||
* @param list_desc - Reference to the list. Created by \ref no_os_list_init.
|
||||
* @param result - If not null, result is filled with:
|
||||
* @param data - Content of the list element, NULL if some error occur.
|
||||
* @return \n
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
* @note If the content of an element can be 0 then the result must be checked
|
||||
* to see if the functions has succeded
|
||||
*/
|
||||
typedef int32_t (*f_read)(struct no_os_list_desc *list_desc, void **data);
|
||||
|
||||
/**
|
||||
* @brief Read and remove an element from the list.
|
||||
* @param list_desc - Reference to the list. Created by \ref no_os_list_init.
|
||||
* @param result - If not null, result is filled with:
|
||||
* @param data - Content of the list element, NULL if some error occur.
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -1 : Otherwise
|
||||
*/
|
||||
typedef int32_t (*f_get)(struct no_os_list_desc *list_desc, void **data);
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @enum no_os_adapter_type
|
||||
* @brief Selects functionalities for functions in \ref no_os_list_desc
|
||||
*/
|
||||
enum no_os_adapter_type {
|
||||
/** Default type is NO_OS_LIST_STACK */
|
||||
NO_OS_LIST_DEFAULT,
|
||||
/**
|
||||
* Functions for a FIFO list (First-in first-out). Elements are inserted
|
||||
* in one end and extracted from the other end.
|
||||
* - \e Push: Insert element
|
||||
* - \e Pop: Get next element (Read and remove)
|
||||
* - \e Top_next: Read next element
|
||||
* - \e Back: Read first element
|
||||
* - \e Swap: Edit the content of the next element
|
||||
*/
|
||||
NO_OS_LIST_QUEUE,
|
||||
/**
|
||||
* Functions for a LIFO list (Last-in first-out). Elements are inserted
|
||||
* and extracted only from the same end.
|
||||
* - \e Push: Insert element
|
||||
* - \e Pop: Get top element (Read and remove)
|
||||
* - \e Top_next: Read top element
|
||||
* - \e Back: Read bottom element
|
||||
* - \e Swap: Edit the content of the top element
|
||||
*/
|
||||
NO_OS_LIST_STACK,
|
||||
/**
|
||||
* Functions for ordered list. The order of element is determinated
|
||||
* usinge the \ref f_cmp.
|
||||
* - \e Push: Insert element
|
||||
* - \e Pop: Get lowest element (Read and remove)
|
||||
* - \e Top_next: Read lowest element
|
||||
* - \e Back: Read the biggest element
|
||||
* - \e Swap: Edit the lowest element
|
||||
*/
|
||||
NO_OS_LIST_PRIORITY_LIST
|
||||
};
|
||||
|
||||
struct no_os_list_desc {
|
||||
/** Refer to \ref no_os_adapter_type */
|
||||
f_add push;
|
||||
/** Refer to \ref no_os_adapter_type */
|
||||
f_get pop;
|
||||
/** Refer to \ref no_os_adapter_type */
|
||||
f_read top_next;
|
||||
/** Refer to \ref no_os_adapter_type */
|
||||
f_read back;
|
||||
/** Refer to \ref no_os_adapter_type */
|
||||
f_edit swap;
|
||||
/** Structure storing the list internal parameters */
|
||||
void *priv_desc;
|
||||
};
|
||||
|
||||
int32_t no_os_list_init(struct no_os_list_desc **list_desc,
|
||||
enum no_os_adapter_type type,
|
||||
f_cmp comparator);
|
||||
int32_t no_os_list_remove(struct no_os_list_desc *list_desc);
|
||||
int32_t no_os_list_get_size(struct no_os_list_desc *list_desc,
|
||||
uint32_t *out_size);
|
||||
|
||||
/**
|
||||
* @name Iterator functions
|
||||
* An iterator is used to iterate through the list. For a list, any number of
|
||||
* iterators can be created. All must be removed before removing a list.
|
||||
* @{
|
||||
*/
|
||||
int32_t no_os_iterator_init(struct no_os_iterator **iter,
|
||||
struct no_os_list_desc *list_desc,
|
||||
bool start);
|
||||
int32_t no_os_iterator_remove(struct no_os_iterator *iter);
|
||||
int32_t no_os_iterator_move(struct no_os_iterator *iter, int32_t steps);
|
||||
int32_t no_os_iterator_move_to_idx(struct no_os_iterator *iter, int32_t idx);
|
||||
int32_t no_os_iterator_find(struct no_os_iterator *iter, void *cmp_data);
|
||||
int32_t no_os_iterator_insert(struct no_os_iterator *iter, void *data,
|
||||
bool after);
|
||||
int32_t no_os_iterator_edit(struct no_os_iterator *iter, void *new_data);
|
||||
int32_t no_os_iterator_read(struct no_os_iterator *iter, void **data);
|
||||
int32_t no_os_iterator_get(struct no_os_iterator *iter, void **data);
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
* @name Operations on the ends of the list
|
||||
* These functions will operate on the first or last element of the list
|
||||
* @{
|
||||
*/
|
||||
int32_t no_os_list_add_first(struct no_os_list_desc *list_desc, void *data);
|
||||
int32_t no_os_list_edit_first(struct no_os_list_desc *list_desc,
|
||||
void *new_data);
|
||||
int32_t no_os_list_read_first(struct no_os_list_desc *list_desc, void **data);
|
||||
int32_t no_os_list_get_first(struct no_os_list_desc *list_desc, void **data);
|
||||
|
||||
int32_t no_os_list_add_last(struct no_os_list_desc *list_desc, void *data);
|
||||
int32_t no_os_list_edit_last(struct no_os_list_desc *list_desc, void *new_data);
|
||||
int32_t no_os_list_read_last(struct no_os_list_desc *list_desc, void **data);
|
||||
int32_t no_os_list_get_last(struct no_os_list_desc *list_desc, void **data);
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
* @name Operations by index
|
||||
* These functions use an index to identify the element in the list.
|
||||
* @{
|
||||
*/
|
||||
int32_t no_os_list_add_idx(struct no_os_list_desc *list_desc, void *data,
|
||||
uint32_t idx);
|
||||
int32_t no_os_list_edit_idx(struct no_os_list_desc *list_desc, void *new_data,
|
||||
uint32_t idx);
|
||||
int32_t no_os_list_read_idx(struct no_os_list_desc *list_desc, void **data,
|
||||
uint32_t idx);
|
||||
int32_t no_os_list_get_idx(struct no_os_list_desc *list_desc, void **data,
|
||||
uint32_t idx);
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
* @name Operations by comparation
|
||||
* These functions use the specified \ref f_cmp at \ref no_os_list_init to identify
|
||||
* the element this will operate on.
|
||||
* @{
|
||||
*/
|
||||
int32_t no_os_list_add_find(struct no_os_list_desc *list_desc, void *data);
|
||||
int32_t no_os_list_edit_find(struct no_os_list_desc *list_desc, void *new_data,
|
||||
void *cmp_data);
|
||||
int32_t no_os_list_read_find(struct no_os_list_desc *list_desc, void **data,
|
||||
void *cmp_data);
|
||||
int32_t no_os_list_get_find(struct no_os_list_desc *list_desc, void **data,
|
||||
void *cmp_data);
|
||||
/** @}*/
|
||||
|
||||
#endif // _NO_OS_LIST_H_
|
||||
@@ -0,0 +1,119 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_mdio.c
|
||||
* @brief Source file for MDIO interface driver.
|
||||
* @author Darius Berghe (darius.berghe@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2023(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#include <errno.h>
|
||||
#include "no_os_mdio.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize the MDIO interface.
|
||||
* @param desc - The MDIO descriptor.
|
||||
* @param param - MDIO parameters.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int no_os_mdio_init(struct no_os_mdio_desc **desc,
|
||||
struct no_os_mdio_init_param *param)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!param || !param->ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->ops->init)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = param->ops->init(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*desc)->id = param->id;
|
||||
(*desc)->c45 = param->c45;
|
||||
(*desc)->addr = param->addr;
|
||||
(*desc)->ops = param->ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by no_os_mdio_init().
|
||||
* @param desc - The MDIO descriptor.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int no_os_mdio_remove(struct no_os_mdio_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->ops->remove)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->ops->remove(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a register using MDIO.
|
||||
* @param desc - The MDIO descriptor.
|
||||
* @param reg - Register address.
|
||||
* For clause 45 reg is constructed using NO_OS_MDIO_C45_ADDR macro.
|
||||
* It is otherwise the plain clause 22 address (0...31).
|
||||
* @param val - Value to write into register.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int no_os_mdio_write(struct no_os_mdio_desc *desc, uint32_t reg, uint16_t val)
|
||||
{
|
||||
if (!desc || !desc->ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->ops->write)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->ops->write(desc, reg, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read a register using MDIO.
|
||||
* @param desc - The MDIO descriptor.
|
||||
* @param reg - Register address.
|
||||
* For clause 45 reg is constructed using NO_OS_MDIO_C45_ADDR macro.
|
||||
* It is otherwise the plain clause 22 address (0...31).
|
||||
* @param val - Value read from register.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int no_os_mdio_read(struct no_os_mdio_desc *desc, uint32_t reg, uint16_t *val)
|
||||
{
|
||||
if (!desc || !desc->ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->ops->read)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->ops->read(desc, reg, val);
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_mdio.h
|
||||
* @brief Header file for MDIO interface driver.
|
||||
* @author Darius Berghe (darius.berghe@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2023(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_MDIO_H_
|
||||
#define _NO_OS_MDIO_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "no_os_util.h"
|
||||
|
||||
#define NO_OS_MDIO_C22_REGS 32
|
||||
#define NO_OS_MDIO_C45_START 0
|
||||
#define NO_OS_MDIO_C22_START 1
|
||||
#define NO_OS_MDIO_START_MASK NO_OS_GENMASK(31, 30)
|
||||
#define NO_OS_MDIO_OP_ADDRESS 0
|
||||
#define NO_OS_MDIO_OP_WRITE 1
|
||||
#define NO_OS_MDIO_OP_READ 2
|
||||
#define NO_OS_MDIO_OP_MASK NO_OS_GENMASK(29, 28)
|
||||
#define NO_OS_MDIO_PHYADDR_MASK NO_OS_GENMASK(27, 23)
|
||||
#define NO_OS_MDIO_REGADDR_MASK NO_OS_GENMASK(22, 18)
|
||||
#define NO_OS_MDIO_TURNAROUND 2
|
||||
#define NO_OS_MDIO_TURNAROUND_MASK NO_OS_GENMASK(17, 16)
|
||||
#define NO_OS_MDIO_DATA_MASK NO_OS_GENMASK(15, 0)
|
||||
#define NO_OS_MDIO_C45_DEVADDR_MASK NO_OS_GENMASK(20, 16)
|
||||
#define NO_OS_MDIO_C45_ADDR(dev, reg) (NO_OS_BIT(31) | no_os_field_prep(NO_OS_MDIO_C45_DEVADDR_MASK, dev) | (uint16_t)reg)
|
||||
|
||||
/**
|
||||
* @struct no_os_mdio_init_param
|
||||
* @brief Parameters for an MDIO slave.
|
||||
*/
|
||||
struct no_os_mdio_init_param {
|
||||
/** Device ID (when using MDIO peripheral), optional. */
|
||||
int id;
|
||||
/** Specifies if clause 45 frame format is supported by the slave,
|
||||
* otherwise clause 22 frame format is used. */
|
||||
bool c45;
|
||||
/** MDIO slave address on the bus. */
|
||||
uint8_t addr;
|
||||
/** Specific implementations of the API. */
|
||||
struct no_os_mdio_ops *ops;
|
||||
/** Platform or implementation specific parameters. */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_mdio_desc
|
||||
* @brief MDIO device descriptor created with no_os_mdio_init().
|
||||
*/
|
||||
struct no_os_mdio_desc {
|
||||
int id;
|
||||
bool c45;
|
||||
uint8_t addr;
|
||||
struct no_os_mdio_ops *ops;
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_mdio_ops
|
||||
* @brief Collection of MDIO ops that point to specific implementations.
|
||||
*/
|
||||
struct no_os_mdio_ops {
|
||||
/** MDIO initialization op */
|
||||
int (*init)(struct no_os_mdio_desc **, struct no_os_mdio_init_param *);
|
||||
/** MDIO write register op */
|
||||
int (*write)(struct no_os_mdio_desc *, uint32_t, uint16_t);
|
||||
/** MDIO read register op */
|
||||
int (*read)(struct no_os_mdio_desc *, uint32_t, uint16_t *);
|
||||
/** MDIO remove op */
|
||||
int (*remove)(struct no_os_mdio_desc *);
|
||||
};
|
||||
|
||||
int no_os_mdio_init(struct no_os_mdio_desc **desc,
|
||||
struct no_os_mdio_init_param *param);
|
||||
int no_os_mdio_remove(struct no_os_mdio_desc *desc);
|
||||
int no_os_mdio_write(struct no_os_mdio_desc *desc, uint32_t reg, uint16_t val);
|
||||
int no_os_mdio_read(struct no_os_mdio_desc *desc, uint32_t reg, uint16_t *val);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,63 @@
|
||||
/*******************************************************************************
|
||||
* @file util/no_os_mutex.c
|
||||
* @brief Implementation of no-OS mutex funtionality.
|
||||
* @author Robert Budai (robert.budai@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2023(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "no_os_mutex.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize mutex.
|
||||
* @param ptr - Pointer toward the mutex.
|
||||
* @return None.
|
||||
*/
|
||||
__attribute__((weak)) void no_os_mutex_init(void **mutex) {}
|
||||
|
||||
/**
|
||||
* @brief Lock mutex.
|
||||
* @param ptr - Pointer toward the mutex.
|
||||
* @return None.
|
||||
*/
|
||||
__attribute__((weak)) void no_os_mutex_lock(void *mutex) {}
|
||||
|
||||
/**
|
||||
* @brief Unlock mutex.
|
||||
* @param ptr - Pointer toward the mutex.
|
||||
* @return None.
|
||||
*/
|
||||
__attribute((weak)) void no_os_mutex_unlock(void *mutex) {}
|
||||
|
||||
/**
|
||||
* @brief Remove mutex.
|
||||
* @param ptr - Pointer toward the mutex.
|
||||
* @return None.
|
||||
*/
|
||||
__attribute__((weak)) void no_os_mutex_remove(void *mutex) {}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*******************************************************************************
|
||||
* @file no_os_mutex.h
|
||||
* @brief Header file of mutex implementation.
|
||||
* @author Robert Budai (robert.budai@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2023(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_MUTEX_H_
|
||||
#define _NO_OS_MUTEX_H_
|
||||
|
||||
/**
|
||||
* @brief Function for no-os mutex initialization and thread safety.
|
||||
* This function is implemented based on different platforms/OS libraries
|
||||
* that NO-OS supports. These mutex functions are used for thread safety
|
||||
* of peripherals. Since these functions don't return error values it is
|
||||
* the developers responsibility to implement the safety checks in case
|
||||
* new mutex implementation is being added, like the following:
|
||||
*
|
||||
* if ((*mutex) == NULL)
|
||||
* {
|
||||
* //code to initialize the mutex
|
||||
* }
|
||||
*
|
||||
* Also these check are responsible not to allocate different mutexes
|
||||
* for the same peripheral descriptor.
|
||||
*/
|
||||
void no_os_mutex_init(void **mutex);
|
||||
|
||||
/**
|
||||
* @brief Function for locking mutex
|
||||
*/
|
||||
void no_os_mutex_lock(void *mutex);
|
||||
|
||||
/**
|
||||
* @brief Function for unlocking mutex
|
||||
*/
|
||||
void no_os_mutex_unlock(void *mutex);
|
||||
|
||||
/**
|
||||
* @brief Function for removing the initialized mutex.
|
||||
* This function is responsible to remove the allocated mutex. This function is
|
||||
* also used by the peripherals mutex thread safety feature and in case
|
||||
* new mutex implementation is going to be added, it is the developers
|
||||
* responsibility to add extra check inside the function while de-allocating the memory.
|
||||
*
|
||||
* if (mutex != NULL)
|
||||
* {
|
||||
* //code to de-allocate mutex
|
||||
* }
|
||||
*/
|
||||
void no_os_mutex_remove(void *mutex);
|
||||
|
||||
#endif // _NO_OS_MUTEX_H_
|
||||
@@ -0,0 +1,202 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_pid.c
|
||||
* @brief Source file for PID control utility.
|
||||
* @author Darius Berghe (darius.berghe@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2023(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#include <errno.h>
|
||||
#include "no_os_pid.h"
|
||||
#include "no_os_alloc.h"
|
||||
#include "no_os_print_log.h"
|
||||
|
||||
struct no_os_pid {
|
||||
int iacc; // integral accumulator
|
||||
int dacc; // derivative accumulator
|
||||
int64_t output; // on 64-bits to avoid overflow
|
||||
struct no_os_pid_config config; // copy of the user-provided configuration
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initialize a PID controller with given configuration
|
||||
* @param pid - Double pointer to a PID descriptor that the function allocates
|
||||
* @param config - PID configuration structure
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -EINVAL : Invalid input
|
||||
* - -ENOMEM : Memory allocation failure
|
||||
*/
|
||||
int no_os_pid_init(struct no_os_pid **pid, struct no_os_pid_config config)
|
||||
{
|
||||
if (!pid)
|
||||
return -EINVAL;
|
||||
|
||||
if (config.output_clip.high < config.output_clip.low)
|
||||
return -EINVAL;
|
||||
|
||||
*pid = no_os_calloc(1, sizeof(**pid));
|
||||
if (!*pid)
|
||||
return -ENOMEM;
|
||||
|
||||
(*pid)->config = config;
|
||||
(*pid)->output = config.initial;
|
||||
(*pid)->iacc = 0;
|
||||
(*pid)->dacc = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform PID control given a controller, a set-point and a process variable.
|
||||
* @param pid - PID descriptor created with no_os_pid_init()
|
||||
* @param SP - Set-point
|
||||
* @param PV - Process variable
|
||||
* @param output - The output of the PID control
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -EINVAL : Invalid input
|
||||
*/
|
||||
int no_os_pid_control(struct no_os_pid *pid, int SP, int PV, int *output)
|
||||
{
|
||||
int err; // error
|
||||
int64_t p; // proportional component
|
||||
int64_t i; // integral component
|
||||
int64_t d; // derivative component
|
||||
struct no_os_pid_range *i_clip;
|
||||
struct no_os_pid_range *output_clip;
|
||||
|
||||
if (!pid || !output)
|
||||
return -EINVAL;
|
||||
|
||||
i_clip = &pid->config.i_clip;
|
||||
output_clip = &pid->config.output_clip;
|
||||
|
||||
// error is the difference between the set point and process variable
|
||||
err = SP - PV;
|
||||
|
||||
// don't control (maintain output) if within hysteresis range
|
||||
if (abs(err) < pid->config.hysteresis) {
|
||||
pr_debug("SP: %d PV: %d --> output: %lu for err=%d\n", SP, PV, pid->output,
|
||||
err);
|
||||
goto end;
|
||||
}
|
||||
|
||||
// compute proportional component
|
||||
p = (int64_t)pid->config.Kp * err;
|
||||
|
||||
// clip integrator accumulator if enabled and if needed
|
||||
if (i_clip->high > i_clip->low) {
|
||||
if (pid->iacc > i_clip->high)
|
||||
pid->iacc = i_clip->high;
|
||||
else if (pid->iacc < i_clip->low)
|
||||
pid->iacc = i_clip->low;
|
||||
}
|
||||
|
||||
// compute integral component
|
||||
i = (int64_t)pid->config.Ki * pid->iacc;
|
||||
|
||||
// compute the derivative component
|
||||
d = (int64_t)pid->config.Kd * (pid->dacc - err);
|
||||
|
||||
// compute the output
|
||||
pid->output = (pid->output * 1000000 - (p + i + d)) / 1000000;
|
||||
pr_debug("SP: %d PV: %d --> output: %ld for p %ld i %ld d %ld err=%d\n", SP, PV,
|
||||
pid->output, p, i, d, err);
|
||||
|
||||
// clip the output if enabled and if needed
|
||||
if (output_clip->high > output_clip->low) {
|
||||
if (pid->output > output_clip->high)
|
||||
pid->output = output_clip->high;
|
||||
else if (pid->output < output_clip->low)
|
||||
pid->output = output_clip->low;
|
||||
}
|
||||
|
||||
// keep track of error history in the integrator accumulator
|
||||
pid->iacc += err;
|
||||
|
||||
// keep track of process variable change rate in the derivative accumulator
|
||||
pid->dacc = err;
|
||||
end:
|
||||
*output = pid->output;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Change the hysteresis.
|
||||
* @param pid - PID descriptor created with no_os_pid_init()
|
||||
* @param hyst - The new hysteresis value
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -EINVAL : Invalid input
|
||||
*/
|
||||
int no_os_pid_hysteresis(struct no_os_pid *pid, unsigned int hyst)
|
||||
{
|
||||
if (!pid)
|
||||
return -EINVAL;
|
||||
|
||||
pid->config.hysteresis = hyst;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset internal accumulators, useful when the same pid descriptor is used to start over.
|
||||
* @param pid - PID descriptor created with no_os_pid_init()
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -EINVAL : Invalid input
|
||||
*/
|
||||
int no_os_pid_reset(struct no_os_pid *pid)
|
||||
{
|
||||
if (!pid)
|
||||
return -EINVAL;
|
||||
|
||||
pid->iacc = 0;
|
||||
pid->dacc = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-initialize a PID controller by freeing the allocated memory
|
||||
* @param pid - PID descriptor created with no_os_pid_init()
|
||||
* @return
|
||||
* - 0 : On success
|
||||
* - -EINVAL : Invalid input
|
||||
*/
|
||||
int no_os_pid_remove(struct no_os_pid *pid)
|
||||
{
|
||||
if (!pid)
|
||||
return -EINVAL;
|
||||
|
||||
no_os_free(pid);
|
||||
pid = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_pid.h
|
||||
* @brief Header file for PID control utility.
|
||||
* @author Darius Berghe (darius.berghe@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2023(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_PID_H
|
||||
#define _NO_OS_PID_H
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @struct no_os_pid_range
|
||||
* @brief Range definition for limiting PID control output or internal integrator accumulator
|
||||
*/
|
||||
struct no_os_pid_range {
|
||||
/* High limit of the range */
|
||||
int high;
|
||||
/** Low limit of the range */
|
||||
int low;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_pid_config
|
||||
* @brief Configuration of the PID
|
||||
*/
|
||||
struct no_os_pid_config {
|
||||
/** Proportional gain (micro-units) */
|
||||
unsigned int Kp;
|
||||
/** Integral gain (micro-units) */
|
||||
unsigned int Ki;
|
||||
/** Derivative gain (micro-units) */
|
||||
unsigned int Kd;
|
||||
/** (Optional) Control supressed when process variable is within set point +/- hysteresis */
|
||||
unsigned int hysteresis;
|
||||
/** (Optional) Boundary limits for integral component */
|
||||
struct no_os_pid_range i_clip;
|
||||
/** (Optional) Boundary limits for the output (for example, for an 8-bit controlled PWM, one would clip the output to 0-255 range) */
|
||||
struct no_os_pid_range output_clip;
|
||||
/** (Optional) Initial output */
|
||||
int initial;
|
||||
};
|
||||
|
||||
struct no_os_pid;
|
||||
|
||||
int no_os_pid_init(struct no_os_pid **pid, struct no_os_pid_config config);
|
||||
int no_os_pid_control(struct no_os_pid *pid, int SP, int PV, int *output);
|
||||
int no_os_pid_hysteresis(struct no_os_pid *pid, unsigned int hyst);
|
||||
int no_os_pid_reset(struct no_os_pid *pid);
|
||||
int no_os_pid_remove(struct no_os_pid *pid);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,132 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_print_log.h
|
||||
* @brief Print messages helpers.
|
||||
* @author Antoniu Miclaus (antoniu.miclaus@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _NO_OS_PRINT_LOG_H_
|
||||
#define _NO_OS_PRINT_LOG_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define NO_OS_LOG_EMERG 0x0
|
||||
#define NO_OS_LOG_ALERT 0x1
|
||||
#define NO_OS_LOG_CRIT 0x2
|
||||
#define NO_OS_LOG_ERR 0x3
|
||||
#define NO_OS_LOG_WARNING 0x4
|
||||
#define NO_OS_LOG_NOTICE 0x5
|
||||
#define NO_OS_LOG_INFO 0x6
|
||||
#define NO_OS_LOG_DEBUG 0x7
|
||||
|
||||
#ifndef NO_OS_LOG_LEVEL
|
||||
#define NO_OS_LOG_LEVEL NO_OS_LOG_INFO
|
||||
#endif
|
||||
|
||||
#if defined(PRINT_TIME)
|
||||
#define pr_time { struct no_os_time _t = no_os_get_time(); \
|
||||
printf("[%5d.%06d] ", _t.s, _t.us); \
|
||||
}
|
||||
#else
|
||||
#define pr_time ;
|
||||
#endif
|
||||
|
||||
#if defined(NO_OS_LOG_LEVEL) && NO_OS_LOG_LEVEL >= NO_OS_LOG_EMERG && NO_OS_LOG_LEVEL <= NO_OS_LOG_DEBUG
|
||||
#define pr_emerg(fmt, args...) do { \
|
||||
pr_time \
|
||||
printf("EMERG: %s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, ##args); \
|
||||
} while (0)
|
||||
#else
|
||||
#define pr_emerg(fmt, args...)
|
||||
#endif
|
||||
|
||||
#if defined(NO_OS_LOG_LEVEL) && NO_OS_LOG_LEVEL >= NO_OS_LOG_ALERT && NO_OS_LOG_LEVEL <= NO_OS_LOG_DEBUG
|
||||
#define pr_alert(fmt, args...) do { \
|
||||
pr_time \
|
||||
printf("ALERT: %s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, ##args); \
|
||||
} while (0)
|
||||
#else
|
||||
#define pr_alert(fmt, args...)
|
||||
#endif
|
||||
|
||||
#if defined(NO_OS_LOG_LEVEL) && NO_OS_LOG_LEVEL >= NO_OS_LOG_CRIT && NO_OS_LOG_LEVEL <= NO_OS_LOG_DEBUG
|
||||
#define pr_crit(fmt, args...) do { \
|
||||
pr_time \
|
||||
printf("CRIT: %s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, ##args); \
|
||||
} while (0)
|
||||
#else
|
||||
#define pr_crit(fmt, args...)
|
||||
#endif
|
||||
|
||||
#if defined(NO_OS_LOG_LEVEL) && NO_OS_LOG_LEVEL >= NO_OS_LOG_ERR && NO_OS_LOG_LEVEL <= NO_OS_LOG_DEBUG
|
||||
#define pr_err(fmt, args...) do { \
|
||||
pr_time \
|
||||
printf("ERR: %s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, ##args); \
|
||||
} while (0)
|
||||
#else
|
||||
#define pr_err(fmt, args...)
|
||||
#endif
|
||||
|
||||
#if defined(NO_OS_LOG_LEVEL) && NO_OS_LOG_LEVEL >= NO_OS_LOG_WARNING && NO_OS_LOG_LEVEL <= NO_OS_LOG_DEBUG
|
||||
#define pr_warning(fmt, args...) do { \
|
||||
pr_time \
|
||||
printf("WARNING: " fmt, ##args); \
|
||||
} while (0)
|
||||
#else
|
||||
#define pr_warning(fmt, args...)
|
||||
#endif
|
||||
|
||||
#if defined(NO_OS_LOG_LEVEL) && NO_OS_LOG_LEVEL >= NO_OS_LOG_NOTICE && NO_OS_LOG_LEVEL <= NO_OS_LOG_DEBUG
|
||||
#define pr_notice(fmt, args...) do { \
|
||||
pr_time \
|
||||
printf("NOTICE: " fmt, ##args); \
|
||||
} while (0)
|
||||
#else
|
||||
#define pr_notice(fmt, args...)
|
||||
#endif
|
||||
|
||||
#if defined(NO_OS_LOG_LEVEL) && NO_OS_LOG_LEVEL >= NO_OS_LOG_INFO && NO_OS_LOG_LEVEL <= NO_OS_LOG_DEBUG
|
||||
#define pr_info(fmt, args...) do { \
|
||||
pr_time \
|
||||
printf(fmt, ##args); \
|
||||
} while(0)
|
||||
#else
|
||||
#define pr_info(fmt, args...)
|
||||
#endif
|
||||
|
||||
#if defined(NO_OS_LOG_LEVEL) && NO_OS_LOG_LEVEL == NO_OS_LOG_DEBUG
|
||||
#define pr_debug(fmt, args...) do { \
|
||||
pr_time \
|
||||
printf("DEBUG: " fmt, ##args); \
|
||||
} while(0)
|
||||
#else
|
||||
#define pr_debug(fmt, args...)
|
||||
#endif
|
||||
|
||||
#endif // _NO_OS_PRINT_LOG_H_
|
||||
@@ -0,0 +1,273 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_pwm.c
|
||||
* @brief Implementation of the PWM Interface
|
||||
* @author Pratyush Mallick (pratyush.mallick@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2023(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "no_os_pwm.h"
|
||||
#include <stdlib.h>
|
||||
#include "no_os_error.h"
|
||||
#include "no_os_mutex.h"
|
||||
|
||||
/**
|
||||
* @brief - PWM mutex
|
||||
*/
|
||||
static void *pwm_mutex_table[PWM_MAX_NUMBER + 1];
|
||||
|
||||
/**
|
||||
* @brief Initialize the PWM peripheral.
|
||||
* @param desc - The PWM descriptor.
|
||||
* @param param - The structure that contains the PWM parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_pwm_init(struct no_os_pwm_desc **desc,
|
||||
const struct no_os_pwm_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!param || !param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->pwm_ops_init)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = param->platform_ops->pwm_ops_init(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
|
||||
no_os_mutex_init(&pwm_mutex_table[param->id]);
|
||||
(*desc)->mutex = pwm_mutex_table[param->id];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by no_os_pwm_init().
|
||||
* @param desc - The PWM descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_pwm_remove(struct no_os_pwm_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->pwm_ops_remove)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_remove(desc->mutex);
|
||||
pwm_mutex_table[desc->id] = NULL;
|
||||
|
||||
return desc->platform_ops->pwm_ops_remove(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable PWM signal generation.
|
||||
* @param desc - The PWM descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_pwm_enable(struct no_os_pwm_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->pwm_ops_enable)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_lock(desc->mutex);
|
||||
return desc->platform_ops->pwm_ops_enable(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable PWM signal generation.
|
||||
* @param desc - The PWM descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_pwm_disable(struct no_os_pwm_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->pwm_ops_disable)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_unlock(desc->mutex);
|
||||
return desc->platform_ops->pwm_ops_disable(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the PWM period value.
|
||||
* @param desc - The PWM descriptor.
|
||||
* @param period_ns - The period value in nanoseconds.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_pwm_set_period(struct no_os_pwm_desc *desc,
|
||||
uint32_t period_ns)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->pwm_ops_set_period)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->pwm_ops_set_period(desc, period_ns);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the PWM period value.
|
||||
* @param desc - The PWM descriptor.
|
||||
* @param period_ns - The period value in nanoseconds.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_pwm_get_period(struct no_os_pwm_desc *desc,
|
||||
uint32_t *period_ns)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->pwm_ops_get_period)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->pwm_ops_get_period(desc, period_ns);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the PWM duty cycle.
|
||||
* @param desc - The PWM descriptor.
|
||||
* @param duty_cycle_ns - Duty cycle in nanoseconds.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_pwm_set_duty_cycle(struct no_os_pwm_desc *desc,
|
||||
uint32_t duty_cycle_ns)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->pwm_ops_set_duty_cycle)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->pwm_ops_set_duty_cycle(desc, duty_cycle_ns);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the PWM duty cycle.
|
||||
* @param desc - The PWM descriptor.
|
||||
* @param duty_cycle_ns - Duty cycle in nanoseconds.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_pwm_get_duty_cycle(struct no_os_pwm_desc *desc,
|
||||
uint32_t *duty_cycle_ns)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->pwm_ops_get_duty_cycle)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->pwm_ops_get_duty_cycle(desc, duty_cycle_ns);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the PWM phase value.
|
||||
* @param desc - The PWM descriptor.
|
||||
* @param phase_ns - Phase value in nanoseconds.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_pwm_set_phase(struct no_os_pwm_desc *desc,
|
||||
uint32_t phase_ns)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->pwm_ops_set_phase)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->pwm_ops_set_phase(desc, phase_ns);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the PWM phase value.
|
||||
* @param desc - The PWM descriptor.
|
||||
* @param phase_ns - Phase value in nanoseconds.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_pwm_get_phase(struct no_os_pwm_desc *desc,
|
||||
uint32_t *phase_ns)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->pwm_ops_get_phase)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->pwm_ops_get_phase(desc, phase_ns);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the PWM polarity.
|
||||
* @param desc - The PWM descriptor.
|
||||
* @param polarity - Polarity value.
|
||||
* Example: NO_OS_PWM_POLARITY_HIGH
|
||||
* NO_OS_PWM_POLARITY_LOW
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_pwm_set_polarity(struct no_os_pwm_desc *desc,
|
||||
enum no_os_pwm_polarity polarity)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->pwm_ops_set_polarity)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->pwm_ops_set_polarity(desc, polarity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the PWM polarity.
|
||||
* @param desc - The PWM descriptor.
|
||||
* @param polarity - Polarity value.
|
||||
* Example: NO_OS_PWM_POLARITY_HIGH
|
||||
* NO_OS_PWM_POLARITY_LOW
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_pwm_get_polarity(struct no_os_pwm_desc *desc,
|
||||
enum no_os_pwm_polarity *polarity)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->pwm_ops_get_polarity)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->pwm_ops_get_polarity(desc, polarity);
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_pwm.h
|
||||
* @brief Header file of PWM Interface
|
||||
* @author Cristian Pop (cristian.pop@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_PWM_H_
|
||||
#define _NO_OS_PWM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define PWM_MAX_NUMBER 4
|
||||
|
||||
/**
|
||||
* @enum no_os_pwm_polarity
|
||||
* @brief Possible polarities of the PWM signal
|
||||
*/
|
||||
enum no_os_pwm_polarity {
|
||||
/** PWM duty cycle is high, idle low */
|
||||
NO_OS_PWM_POLARITY_HIGH,
|
||||
/** PWM duty cycle is low, idle high */
|
||||
NO_OS_PWM_POLARITY_LOW,
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_pwm_init_param
|
||||
* @brief Structure containing the init parameters needed by the PWM generator
|
||||
*/
|
||||
struct no_os_pwm_init_param {
|
||||
/** Pwm id (Ex. Pin number, timer_id) */
|
||||
uint32_t id;
|
||||
/** PWM generator period */
|
||||
uint32_t period_ns;
|
||||
/** PWM generator duty cycle */
|
||||
uint32_t duty_cycle_ns;
|
||||
/** PWM generator phase */
|
||||
uint32_t phase_ns;
|
||||
/** PWM generator polarity */
|
||||
enum no_os_pwm_polarity polarity;
|
||||
/** PWM gpio pin init param*/
|
||||
struct no_os_gpio_init_param *pwm_gpio;
|
||||
/* IRQ ID */
|
||||
uint32_t irq_id;
|
||||
/** PWM callback **/
|
||||
void (*pwm_callback)(void *arg);
|
||||
/** PWM platform specific functions */
|
||||
const struct no_os_pwm_platform_ops *platform_ops;
|
||||
/** PWM extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_pwm_desc
|
||||
* @brief Structure representing an PWM generator device
|
||||
*/
|
||||
struct no_os_pwm_desc {
|
||||
/** PWM mutex*/
|
||||
void *mutex;
|
||||
/** Pwm id */
|
||||
uint32_t id;
|
||||
/** PWM generator period */
|
||||
uint32_t period_ns;
|
||||
/** PWM generator duty cycle */
|
||||
uint32_t duty_cycle_ns;
|
||||
/** PWM generator phase */
|
||||
uint32_t phase_ns;
|
||||
/** PWM generator polarity */
|
||||
enum no_os_pwm_polarity polarity;
|
||||
/** PWM generator enabled */
|
||||
bool enabled;
|
||||
/** PWM gpio pin instance */
|
||||
struct no_os_gpio_desc *pwm_gpio;
|
||||
/* IRQ ID */
|
||||
uint32_t irq_id;
|
||||
/** PWM callback **/
|
||||
void (*pwm_callback)(void* arg);
|
||||
/** PWM platform specific functions */
|
||||
const struct no_os_pwm_platform_ops *platform_ops;
|
||||
/** PWM extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_pwm_platform_ops
|
||||
* @brief Structure holding PWM function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_pwm_platform_ops {
|
||||
/** pwm initialization function pointer */
|
||||
int32_t (*pwm_ops_init)(struct no_os_pwm_desc **,
|
||||
const struct no_os_pwm_init_param *);
|
||||
/** pwm enable function pointer */
|
||||
int32_t (*pwm_ops_enable)(struct no_os_pwm_desc *);
|
||||
/** pwm disable function pointer */
|
||||
int32_t (*pwm_ops_disable)(struct no_os_pwm_desc *);
|
||||
/** pwm set period function pointer */
|
||||
int32_t (*pwm_ops_set_period)(struct no_os_pwm_desc *, uint32_t);
|
||||
/** pwm get period function pointer */
|
||||
int32_t (*pwm_ops_get_period)(struct no_os_pwm_desc *, uint32_t *);
|
||||
/** pwm set duty cycle function pointer */
|
||||
int32_t (*pwm_ops_set_duty_cycle)(struct no_os_pwm_desc *, uint32_t);
|
||||
/** pwm get duty cycle function pointer */
|
||||
int32_t (*pwm_ops_get_duty_cycle)(struct no_os_pwm_desc *, uint32_t *);
|
||||
/** pwm set phase function pointer */
|
||||
int32_t (*pwm_ops_set_phase)(struct no_os_pwm_desc *, uint32_t);
|
||||
/** pwm get phase function pointer */
|
||||
int32_t (*pwm_ops_get_phase)(struct no_os_pwm_desc *, uint32_t *);
|
||||
/** pwm set polarity function pointer */
|
||||
int32_t (*pwm_ops_set_polarity)(struct no_os_pwm_desc *,
|
||||
enum no_os_pwm_polarity);
|
||||
/** pwm get polarity function pointer */
|
||||
int32_t (*pwm_ops_get_polarity)(struct no_os_pwm_desc *,
|
||||
enum no_os_pwm_polarity *);
|
||||
/** pwm remove function pointer */
|
||||
int32_t(*pwm_ops_remove)(struct no_os_pwm_desc *);
|
||||
};
|
||||
|
||||
/* Initialize the PWM generator device */
|
||||
int32_t no_os_pwm_init(struct no_os_pwm_desc **desc,
|
||||
const struct no_os_pwm_init_param *param);
|
||||
|
||||
/* Free the resources used by the PWM generator device */
|
||||
int32_t no_os_pwm_remove(struct no_os_pwm_desc *desc);
|
||||
|
||||
/* Enable PWM generator device */
|
||||
int32_t no_os_pwm_enable(struct no_os_pwm_desc *desc);
|
||||
|
||||
/* Disable PWM generator device */
|
||||
int32_t no_os_pwm_disable(struct no_os_pwm_desc *desc);
|
||||
|
||||
/* Set period of PWM generator device */
|
||||
int32_t no_os_pwm_set_period(struct no_os_pwm_desc *desc,
|
||||
uint32_t period_ns);
|
||||
|
||||
/* Get period of PWM generator device */
|
||||
int32_t no_os_pwm_get_period(struct no_os_pwm_desc *desc,
|
||||
uint32_t *period_ns);
|
||||
|
||||
/* Set duty cycle of PWM generator device */
|
||||
int32_t no_os_pwm_set_duty_cycle(struct no_os_pwm_desc *desc,
|
||||
uint32_t duty_cycle_ns);
|
||||
|
||||
/* Get period of PWM generator device */
|
||||
int32_t no_os_pwm_get_duty_cycle(struct no_os_pwm_desc *desc,
|
||||
uint32_t *duty_cycle_ns);
|
||||
|
||||
/* Set the phase of PWM generator channel */
|
||||
int32_t no_os_pwm_set_phase(struct no_os_pwm_desc *desc,
|
||||
uint32_t phase_ns);
|
||||
|
||||
/* Get the phase of PWM generator channel */
|
||||
int32_t no_os_pwm_get_phase(struct no_os_pwm_desc *desc,
|
||||
uint32_t *phase_ns);
|
||||
|
||||
/* Set polarity of PWM generator device */
|
||||
int32_t no_os_pwm_set_polarity(struct no_os_pwm_desc *desc,
|
||||
enum no_os_pwm_polarity polarity);
|
||||
|
||||
/* Set polarity of PWM generator device */
|
||||
int32_t no_os_pwm_get_polarity(struct no_os_pwm_desc *desc,
|
||||
enum no_os_pwm_polarity *polarity);
|
||||
|
||||
#endif // _NO_OS_PWM_H_
|
||||
@@ -0,0 +1,91 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_rtc.h
|
||||
* @brief Header of the RTC interface
|
||||
* @author Andrei Drimbarean (andrei.drimbarean@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _NO_OS_RTC_H_
|
||||
#define _NO_OS_RTC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @struct no_os_rtc_desc
|
||||
* @brief Structure holding RTC descriptor.
|
||||
*/
|
||||
struct no_os_rtc_desc {
|
||||
/** ID of the real time clock core. */
|
||||
uint8_t id;
|
||||
/** Frequency of the RTC */
|
||||
uint32_t freq;
|
||||
/** Load value of the RTC */
|
||||
uint32_t load;
|
||||
/** Device specific RTC parameters. */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_rtc_init_param
|
||||
* @brief Structure holding RTC initialization parameters.
|
||||
*/
|
||||
struct no_os_rtc_init_param {
|
||||
/** ID of the real time clock core. */
|
||||
uint8_t id;
|
||||
/** Frequency of the RTC */
|
||||
uint32_t freq;
|
||||
/** Load value of the RTC */
|
||||
uint32_t load;
|
||||
/** Device specific RTC parameters. */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/** Initialize the RTC peripheral. */
|
||||
int32_t no_os_rtc_init(struct no_os_rtc_desc **device,
|
||||
struct no_os_rtc_init_param *init_param);
|
||||
|
||||
/** Free the resources allocated by no_os_rtc_init(). */
|
||||
int32_t no_os_rtc_remove(struct no_os_rtc_desc *dev);
|
||||
|
||||
/** Start the real time clock. */
|
||||
int32_t no_os_rtc_start(struct no_os_rtc_desc *dev);
|
||||
|
||||
/** Stop the real time clock. */
|
||||
int32_t no_os_rtc_stop(struct no_os_rtc_desc *dev);
|
||||
|
||||
/** Get the current count for the real time clock. */
|
||||
int32_t no_os_rtc_get_cnt(struct no_os_rtc_desc *dev, uint32_t *tmr_cnt);
|
||||
|
||||
/** Set the current count for the real time clock. */
|
||||
int32_t no_os_rtc_set_cnt(struct no_os_rtc_desc *dev, uint32_t tmr_cnt);
|
||||
|
||||
/** Set the time at which an interrupt will occur */
|
||||
int32_t no_os_rtc_set_irq_time(struct no_os_rtc_desc *dev, uint32_t irq_time);
|
||||
|
||||
#endif // _NO_OS_RTC_H_
|
||||
@@ -0,0 +1,63 @@
|
||||
/*******************************************************************************
|
||||
* @file util/no_os_semaphore.c
|
||||
* @brief Implementation of no-OS semaphore funtionality.
|
||||
* @author Robert Budai (robert.budai@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2023(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "no_os_semaphore.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize semaphore.
|
||||
* @param ptr - Pointer toward the semaphore.
|
||||
* @return None.
|
||||
*/
|
||||
__attribute__((weak)) void no_os_semaphore_init(void **semaphore) {}
|
||||
|
||||
/**
|
||||
* @brief Take token from semaphore.
|
||||
* @param ptr - Pointer toward the semaphore.
|
||||
* @return None.
|
||||
*/
|
||||
__attribute__((weak)) void no_os_semaphore_take(void *semaphore) {}
|
||||
|
||||
/**
|
||||
* @brief Give token to semaphore
|
||||
* @param ptr - Pointer toward the semaphore.
|
||||
* @return None.
|
||||
*/
|
||||
__attribute((weak)) void no_os_semaphore_give(void *semaphore) {}
|
||||
|
||||
/**
|
||||
* @brief Remove semaphore.
|
||||
* @param ptr - Pointer toward the semaphore.
|
||||
* @return None.
|
||||
*/
|
||||
__attribute__((weak)) void no_os_semaphore_remove(void *semaphore) {}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*******************************************************************************
|
||||
* @file no_os_semaphore.h
|
||||
* @brief Header file of semaphore implementation.
|
||||
* @author Robert Budai (robert.budai@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2023(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_SEMAPHORE_H_
|
||||
#define _NO_OS_SEMAPHORE_H_
|
||||
|
||||
/* Initialize semaphore */
|
||||
void no_os_semaphore_init(void **semaphore);
|
||||
|
||||
/* Take token from semaphore */
|
||||
void no_os_semaphore_take(void *semaphore);
|
||||
|
||||
/* Give token to semaphore */
|
||||
void no_os_semaphore_give(void *semaphore);
|
||||
|
||||
/* Remove semaphore */
|
||||
void no_os_semaphore_remove(void *semaphore);
|
||||
|
||||
#endif // _NO_OS_SEMAPHORE_H_
|
||||
@@ -0,0 +1,68 @@
|
||||
#include <stdint.h>
|
||||
|
||||
const uint16_t no_os_sine_lut_16[512] = {
|
||||
0x8000, 0x8192, 0x8324, 0x84b6, 0x8647, 0x87d9, 0x896a, 0x8afb,
|
||||
0x8c8b, 0x8e1b, 0x8fab, 0x9139, 0x92c7, 0x9455, 0x95e1, 0x976d,
|
||||
0x98f8, 0x9a82, 0x9c0b, 0x9d93, 0x9f19, 0xa09f, 0xa223, 0xa3a6,
|
||||
0xa527, 0xa6a7, 0xa826, 0xa9a3, 0xab1f, 0xac98, 0xae10, 0xaf87,
|
||||
0xb0fb, 0xb26e, 0xb3de, 0xb54d, 0xb6b9, 0xb824, 0xb98c, 0xbaf2,
|
||||
0xbc56, 0xbdb7, 0xbf17, 0xc073, 0xc1cd, 0xc325, 0xc47a, 0xc5cc,
|
||||
0xc71c, 0xc869, 0xc9b3, 0xcafb, 0xcc3f, 0xcd81, 0xcebf, 0xcffb,
|
||||
0xd133, 0xd268, 0xd39a, 0xd4c9, 0xd5f5, 0xd71d, 0xd842, 0xd964,
|
||||
0xda82, 0xdb9c, 0xdcb3, 0xddc7, 0xded7, 0xdfe3, 0xe0eb, 0xe1f0,
|
||||
0xe2f1, 0xe3ee, 0xe4e8, 0xe5dd, 0xe6cf, 0xe7bc, 0xe8a6, 0xe98b,
|
||||
0xea6d, 0xeb4a, 0xec23, 0xecf8, 0xedc9, 0xee96, 0xef5e, 0xf022,
|
||||
0xf0e2, 0xf19d, 0xf254, 0xf307, 0xf3b5, 0xf45f, 0xf504, 0xf5a5,
|
||||
0xf641, 0xf6d8, 0xf76b, 0xf7fa, 0xf884, 0xf909, 0xf989, 0xfa05,
|
||||
0xfa7c, 0xfaee, 0xfb5c, 0xfbc5, 0xfc29, 0xfc88, 0xfce3, 0xfd39,
|
||||
0xfd89, 0xfdd5, 0xfe1d, 0xfe5f, 0xfe9c, 0xfed5, 0xff09, 0xff37,
|
||||
0xff61, 0xff86, 0xffa6, 0xffc1, 0xffd8, 0xffe9, 0xfff5, 0xfffd,
|
||||
0xffff, 0xfffd, 0xfff5, 0xffe9, 0xffd8, 0xffc1, 0xffa6, 0xff86,
|
||||
0xff61, 0xff37, 0xff09, 0xfed5, 0xfe9c, 0xfe5f, 0xfe1d, 0xfdd5,
|
||||
0xfd89, 0xfd39, 0xfce3, 0xfc88, 0xfc29, 0xfbc5, 0xfb5c, 0xfaee,
|
||||
0xfa7c, 0xfa05, 0xf989, 0xf909, 0xf884, 0xf7fa, 0xf76b, 0xf6d8,
|
||||
0xf641, 0xf5a5, 0xf504, 0xf45f, 0xf3b5, 0xf307, 0xf254, 0xf19d,
|
||||
0xf0e2, 0xf022, 0xef5e, 0xee96, 0xedc9, 0xecf8, 0xec23, 0xeb4a,
|
||||
0xea6d, 0xe98b, 0xe8a6, 0xe7bc, 0xe6cf, 0xe5dd, 0xe4e8, 0xe3ee,
|
||||
0xe2f1, 0xe1f0, 0xe0eb, 0xdfe3, 0xded7, 0xddc7, 0xdcb3, 0xdb9c,
|
||||
0xda82, 0xd964, 0xd842, 0xd71d, 0xd5f5, 0xd4c9, 0xd39a, 0xd268,
|
||||
0xd133, 0xcffb, 0xcebf, 0xcd81, 0xcc3f, 0xcafb, 0xc9b3, 0xc869,
|
||||
0xc71c, 0xc5cc, 0xc47a, 0xc325, 0xc1cd, 0xc073, 0xbf17, 0xbdb7,
|
||||
0xbc56, 0xbaf2, 0xb98c, 0xb824, 0xb6b9, 0xb54d, 0xb3de, 0xb26e,
|
||||
0xb0fb, 0xaf87, 0xae10, 0xac98, 0xab1f, 0xa9a3, 0xa826, 0xa6a7,
|
||||
0xa527, 0xa3a6, 0xa223, 0xa09f, 0x9f19, 0x9d93, 0x9c0b, 0x9a82,
|
||||
0x98f8, 0x976d, 0x95e1, 0x9455, 0x92c7, 0x9139, 0x8fab, 0x8e1b,
|
||||
0x8c8b, 0x8afb, 0x896a, 0x87d9, 0x8647, 0x84b6, 0x8324, 0x8192,
|
||||
0x8000, 0x7e6d, 0x7cdb, 0x7b49, 0x79b8, 0x7826, 0x7695, 0x7504,
|
||||
0x7374, 0x71e4, 0x7054, 0x6ec6, 0x6d38, 0x6baa, 0x6a1e, 0x6892,
|
||||
0x6707, 0x657d, 0x63f4, 0x626c, 0x60e6, 0x5f60, 0x5ddc, 0x5c59,
|
||||
0x5ad8, 0x5958, 0x57d9, 0x565c, 0x54e0, 0x5367, 0x51ef, 0x5078,
|
||||
0x4f04, 0x4d91, 0x4c21, 0x4ab2, 0x4946, 0x47db, 0x4673, 0x450d,
|
||||
0x43a9, 0x4248, 0x40e8, 0x3f8c, 0x3e32, 0x3cda, 0x3b85, 0x3a33,
|
||||
0x38e3, 0x3796, 0x364c, 0x3504, 0x33c0, 0x327e, 0x3140, 0x3004,
|
||||
0x2ecc, 0x2d97, 0x2c65, 0x2b36, 0x2a0a, 0x28e2, 0x27bd, 0x269b,
|
||||
0x257d, 0x2463, 0x234c, 0x2238, 0x2128, 0x201c, 0x1f14, 0x1e0f,
|
||||
0x1d0e, 0x1c11, 0x1b17, 0x1a22, 0x1930, 0x1843, 0x1759, 0x1674,
|
||||
0x1592, 0x14b5, 0x13dc, 0x1307, 0x1236, 0x1169, 0x10a1, 0xfdd,
|
||||
0xf1d, 0xe62, 0xdab, 0xcf8, 0xc4a, 0xba0, 0xafb, 0xa5a,
|
||||
0x9be, 0x927, 0x894, 0x805, 0x77b, 0x6f6, 0x676, 0x5fa,
|
||||
0x583, 0x511, 0x4a3, 0x43a, 0x3d6, 0x377, 0x31c, 0x2c6,
|
||||
0x276, 0x22a, 0x1e2, 0x1a0, 0x163, 0x12a, 0xf6, 0xc8,
|
||||
0x9e, 0x79, 0x59, 0x3e, 0x27, 0x16, 0xa, 0x2,
|
||||
0x0, 0x2, 0xa, 0x16, 0x27, 0x3e, 0x59, 0x79,
|
||||
0x9e, 0xc8, 0xf6, 0x12a, 0x163, 0x1a0, 0x1e2, 0x22a,
|
||||
0x276, 0x2c6, 0x31c, 0x377, 0x3d6, 0x43a, 0x4a3, 0x511,
|
||||
0x583, 0x5fa, 0x676, 0x6f6, 0x77b, 0x805, 0x894, 0x927,
|
||||
0x9be, 0xa5a, 0xafb, 0xba0, 0xc4a, 0xcf8, 0xdab, 0xe62,
|
||||
0xf1d, 0xfdd, 0x10a1, 0x1169, 0x1236, 0x1307, 0x13dc, 0x14b5,
|
||||
0x1592, 0x1674, 0x1759, 0x1843, 0x1930, 0x1a22, 0x1b17, 0x1c11,
|
||||
0x1d0e, 0x1e0f, 0x1f14, 0x201c, 0x2128, 0x2238, 0x234c, 0x2463,
|
||||
0x257d, 0x269b, 0x27bd, 0x28e2, 0x2a0a, 0x2b36, 0x2c65, 0x2d97,
|
||||
0x2ecc, 0x3004, 0x3140, 0x327e, 0x33c0, 0x3504, 0x364c, 0x3796,
|
||||
0x38e3, 0x3a33, 0x3b85, 0x3cda, 0x3e32, 0x3f8c, 0x40e8, 0x4248,
|
||||
0x43a9, 0x450d, 0x4673, 0x47db, 0x4946, 0x4ab2, 0x4c21, 0x4d91,
|
||||
0x4f04, 0x5078, 0x51ef, 0x5367, 0x54e0, 0x565c, 0x57d9, 0x5958,
|
||||
0x5ad8, 0x5c59, 0x5ddc, 0x5f60, 0x60e6, 0x626c, 0x63f4, 0x657d,
|
||||
0x6707, 0x6892, 0x6a1e, 0x6baa, 0x6d38, 0x6ec6, 0x7054, 0x71e4,
|
||||
0x7374, 0x7504, 0x7695, 0x7826, 0x79b8, 0x7b49, 0x7cdb, 0x7e6d,
|
||||
};
|
||||
@@ -0,0 +1,278 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_spi.c
|
||||
* @brief Implementation of the SPI Interface
|
||||
* @author Antoniu Miclaus (antoniu.miclaus@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "no_os_spi.h"
|
||||
#include <stdlib.h>
|
||||
#include "no_os_error.h"
|
||||
#include "no_os_mutex.h"
|
||||
#include "no_os_alloc.h"
|
||||
|
||||
/**
|
||||
* @brief spi_table contains the pointers towards the SPI buses
|
||||
*/
|
||||
static void *spi_table[SPI_MAX_BUS_NUMBER + 1];
|
||||
|
||||
/**
|
||||
* @brief Initialize the SPI communication peripheral.
|
||||
* @param desc - The SPI descriptor.
|
||||
* @param param - The structure that contains the SPI parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_spi_init(struct no_os_spi_desc **desc,
|
||||
const struct no_os_spi_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!param || !param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->init)
|
||||
return -ENOSYS;
|
||||
if (param->device_id > SPI_MAX_BUS_NUMBER)
|
||||
return -EINVAL;
|
||||
// Initializing BUS descriptor
|
||||
if (!spi_table[param->device_id]) {
|
||||
ret = no_os_spibus_init(param);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
// Initilize SPI descriptor
|
||||
ret = param->platform_ops->init(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
(*desc)->bus = spi_table[param->device_id];
|
||||
(*desc)->bus->slave_number++;
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
(*desc)->parent = param->parent;
|
||||
(*desc)->platform_delays = param->platform_delays;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the SPI bus communication peripheral.
|
||||
* @param param - The structure that containes the SPI bus parameters
|
||||
* @return 0 in case of success, error code otherwise
|
||||
*/
|
||||
int32_t no_os_spibus_init(const struct no_os_spi_init_param *param)
|
||||
{
|
||||
struct no_os_spibus_desc *bus = (struct no_os_spibus_desc *)no_os_calloc(1,
|
||||
sizeof(struct no_os_spibus_desc));
|
||||
|
||||
if (!bus)
|
||||
return -ENOMEM;
|
||||
|
||||
no_os_mutex_init(&(bus->mutex));
|
||||
|
||||
bus->slave_number = 0;
|
||||
bus->device_id = param->device_id;
|
||||
bus->max_speed_hz = param->max_speed_hz;
|
||||
bus->mode = param->mode;
|
||||
bus->bit_order = param->bit_order;
|
||||
bus->platform_ops = param->platform_ops;
|
||||
bus->extra = param->extra;
|
||||
|
||||
spi_table[param->device_id] = bus;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by no_os_spi_init().
|
||||
* @param desc - The SPI descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_spi_remove(struct no_os_spi_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (desc->bus)
|
||||
no_os_spibus_remove(desc->bus->device_id);
|
||||
|
||||
if (!desc->platform_ops->remove)
|
||||
return -ENOSYS;
|
||||
return desc->platform_ops->remove(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes SPI bus instance
|
||||
* @param bus_number - SPI bus number
|
||||
*/
|
||||
void no_os_spibus_remove(uint32_t bus_number)
|
||||
{
|
||||
struct no_os_spibus_desc *bus = (struct no_os_spibus_desc *)
|
||||
spi_table[bus_number];
|
||||
|
||||
if (bus->slave_number > 0)
|
||||
bus->slave_number--;
|
||||
|
||||
if (bus->slave_number == 0) {
|
||||
no_os_mutex_remove(bus->mutex);
|
||||
|
||||
if (bus) {
|
||||
no_os_free(bus);
|
||||
bus = NULL;
|
||||
spi_table[bus_number] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write and read data to/from SPI.
|
||||
* @param desc - The SPI descriptor.
|
||||
* @param data - The buffer with the transmitted/received data.
|
||||
* @param bytes_number - Number of bytes to write/read.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_spi_write_and_read(struct no_os_spi_desc *desc,
|
||||
uint8_t *data,
|
||||
uint16_t bytes_number)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->write_and_read)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_lock(desc->bus->mutex);
|
||||
ret = desc->platform_ops->write_and_read(desc, data, bytes_number);
|
||||
no_os_mutex_unlock(desc->bus->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Iterate over head list and send all spi messages
|
||||
* @param desc - The SPI descriptor.
|
||||
* @param msgs - Array of messages.
|
||||
* @param len - Number of messages in the array.
|
||||
* @return 0 in case of success, negativ error code otherwise.
|
||||
*/
|
||||
int32_t no_os_spi_transfer(struct no_os_spi_desc *desc,
|
||||
struct no_os_spi_msg *msgs,
|
||||
uint32_t len)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
uint32_t i;
|
||||
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (desc->platform_ops->transfer)
|
||||
return desc->platform_ops->transfer(desc, msgs, len);
|
||||
|
||||
no_os_mutex_lock(desc->bus->mutex);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (msgs[i].rx_buff != msgs[i].tx_buff || !msgs[i].tx_buff) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
ret = no_os_spi_write_and_read(desc, msgs[i].rx_buff,
|
||||
msgs[i].bytes_number);
|
||||
if (NO_OS_IS_ERR_VALUE(ret)) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
no_os_mutex_unlock(desc->bus->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transfer a list of messages using DMA and busy wait for the completion
|
||||
* @param desc - The SPI descriptor.
|
||||
* @param msgs - Array of messages.
|
||||
* @param len - Number of messages in the array.
|
||||
* @return 0 in case of success, negativ error code otherwise.
|
||||
*/
|
||||
int32_t no_os_spi_transfer_dma(struct no_os_spi_desc *desc,
|
||||
struct no_os_spi_msg *msgs,
|
||||
uint32_t len)
|
||||
{
|
||||
if (!desc || !desc->platform_ops || !msgs || !len)
|
||||
return -EINVAL;
|
||||
|
||||
if (desc->platform_ops->transfer_dma)
|
||||
return desc->platform_ops->transfer_dma(desc, msgs, len);
|
||||
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transfer a list of messages using DMA. The function will return after the
|
||||
* first transfer is started. Once all the transfers are complete, a callback
|
||||
* will be called.
|
||||
* @param desc - The SPI descriptor.
|
||||
* @param msgs - Array of messages.
|
||||
* @param len - Number of messages in the array.
|
||||
* @param callback - A function which will be called after all the transfers are done.
|
||||
* @param ctx - User specific data which should be passed to the callback function.
|
||||
* @return 0 in case of success, negativ error code otherwise.
|
||||
*/
|
||||
int32_t no_os_spi_transfer_dma_async(struct no_os_spi_desc *desc,
|
||||
struct no_os_spi_msg *msgs,
|
||||
uint32_t len,
|
||||
void (*callback)(void *),
|
||||
void *ctx)
|
||||
{
|
||||
if (!desc || !desc->platform_ops || !msgs || !len)
|
||||
return -EINVAL;
|
||||
|
||||
if (desc->platform_ops->transfer_dma_async)
|
||||
return desc->platform_ops->transfer_dma_async(desc, msgs, len,
|
||||
callback, ctx);
|
||||
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort SPI transfers.
|
||||
* @param desc - The SPI descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int32_t no_os_spi_transfer_abort(struct no_os_spi_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->transfer_abort)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->transfer_abort(desc);
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_spi.h
|
||||
* @brief Header file of SPI Interface
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _NO_OS_SPI_H_
|
||||
#define _NO_OS_SPI_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define NO_OS_SPI_CPHA 0x01
|
||||
#define NO_OS_SPI_CPOL 0x02
|
||||
#define SPI_MAX_BUS_NUMBER 8
|
||||
|
||||
/**
|
||||
* @enum no_os_spi_mode
|
||||
* @brief SPI configuration for clock phase and polarity.
|
||||
*/
|
||||
enum no_os_spi_mode {
|
||||
/** Data on rising, shift out on falling */
|
||||
NO_OS_SPI_MODE_0 = (0 | 0),
|
||||
/** Data on falling, shift out on rising */
|
||||
NO_OS_SPI_MODE_1 = (0 | NO_OS_SPI_CPHA),
|
||||
/** Data on rising, shift out on falling */
|
||||
NO_OS_SPI_MODE_2 = (NO_OS_SPI_CPOL | 0),
|
||||
/** Data on falling, shift out on rising */
|
||||
NO_OS_SPI_MODE_3 = (NO_OS_SPI_CPOL | NO_OS_SPI_CPHA)
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum no_os_spi_bit_order
|
||||
* @brief SPI configuration for bit order (MSB/LSB).
|
||||
*/
|
||||
enum no_os_spi_bit_order {
|
||||
/** Most-significant bit (MSB) first */
|
||||
NO_OS_SPI_BIT_ORDER_MSB_FIRST = 0,
|
||||
/** Least-significant bit (LSB) first */
|
||||
NO_OS_SPI_BIT_ORDER_LSB_FIRST = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum no_os_spi_lanes
|
||||
* @brief SPI configuration for number of lanes.
|
||||
*/
|
||||
enum no_os_spi_lanes {
|
||||
/** Single Lane */
|
||||
NO_OS_SPI_SINGLE_LANE,
|
||||
/** Dual Lane */
|
||||
NO_OS_SPI_DUAL_LANE,
|
||||
/** Quad Lane */
|
||||
NO_OS_SPI_QUAD_LANE,
|
||||
/** Octo Lane */
|
||||
NO_OS_SPI_OCTO_LANE,
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_spi_msg_list
|
||||
* @brief List item describing a SPI transfer
|
||||
*/
|
||||
struct no_os_spi_msg {
|
||||
/** Buffer with data to send. If NULL, 0x00 will be sent */
|
||||
uint8_t *tx_buff;
|
||||
/** Buffer where to store data. If NULL, incoming data won't be saved */
|
||||
uint8_t *rx_buff;
|
||||
/** Length of buffers. Must have equal size. */
|
||||
uint32_t bytes_number;
|
||||
/** If set, CS will be deasserted after the transfer */
|
||||
uint8_t cs_change;
|
||||
/**
|
||||
* Minimum delay (in us) between the CS de-assert event of the current message
|
||||
* and the assert of the next one.
|
||||
*/
|
||||
uint32_t cs_change_delay;
|
||||
/** Delay (in us) between the CS assert and the first SCLK edge. */
|
||||
uint32_t cs_delay_first;
|
||||
/** Delay (in us) between the last SCLK edge and the CS deassert */
|
||||
uint32_t cs_delay_last;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_platform_spi_delays
|
||||
* @brief Delays resulted from components in the SPI signal path. The values is ns.
|
||||
*/
|
||||
struct no_os_platform_spi_delays {
|
||||
uint32_t cs_delay_first;
|
||||
uint32_t cs_delay_last;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_spi_platform_ops
|
||||
* @brief Structure holding SPI function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_spi_platform_ops ;
|
||||
|
||||
/**
|
||||
* @struct no_os_spi_init_param
|
||||
* @brief Structure holding the parameters for SPI initialization
|
||||
*/
|
||||
struct no_os_spi_init_param {
|
||||
/** Device ID */
|
||||
uint32_t device_id;
|
||||
/** maximum transfer speed */
|
||||
uint32_t max_speed_hz;
|
||||
/** SPI chip select */
|
||||
uint8_t chip_select;
|
||||
/** SPI mode */
|
||||
enum no_os_spi_mode mode;
|
||||
/** SPI bit order */
|
||||
enum no_os_spi_bit_order bit_order;
|
||||
/** SPI Lanes */
|
||||
enum no_os_spi_lanes lanes;
|
||||
/** SPI bus platform ops */
|
||||
const struct no_os_spi_platform_ops *platform_ops;
|
||||
/** SPI delays */
|
||||
struct no_os_platform_spi_delays platform_delays;
|
||||
/** SPI extra parameters (device specific) */
|
||||
void *extra;
|
||||
/** Parent of the device */
|
||||
struct no_os_spi_desc *parent;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_spibus_desc
|
||||
* @brief SPI bus descriptor
|
||||
*/
|
||||
struct no_os_spibus_desc {
|
||||
/** SPI bus mutex (lock) */
|
||||
void *mutex;
|
||||
/** SPI bus slave number*/
|
||||
uint8_t slave_number;
|
||||
/** SPI bus device id */
|
||||
uint32_t device_id;
|
||||
/** SPI bus max speed */
|
||||
uint32_t max_speed_hz;
|
||||
/** SPI bus mode */
|
||||
enum no_os_spi_mode mode;
|
||||
/** SPI bus bit order */
|
||||
enum no_os_spi_bit_order bit_order;
|
||||
/** SPI Lanes */
|
||||
enum no_os_spi_lanes lanes;
|
||||
/** SPI bus platform ops */
|
||||
const struct no_os_spi_platform_ops *platform_ops;
|
||||
/** SPI bus extra */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_spi_desc
|
||||
* @brief Structure holding SPI descriptor.
|
||||
*/
|
||||
struct no_os_spi_desc {
|
||||
/** SPI bus address */
|
||||
struct no_os_spibus_desc *bus;
|
||||
/** SPI bus number (0 for SPI0, 1 for SPI1, ...) */
|
||||
uint32_t device_id;
|
||||
/** maximum transfer speed */
|
||||
uint32_t max_speed_hz;
|
||||
/** SPI chip select */
|
||||
uint8_t chip_select;
|
||||
/** SPI mode */
|
||||
enum no_os_spi_mode mode;
|
||||
/** SPI bit order */
|
||||
enum no_os_spi_bit_order bit_order;
|
||||
/** SPI Lanes */
|
||||
enum no_os_spi_lanes lanes;
|
||||
/** SPI bus platform ops */
|
||||
const struct no_os_spi_platform_ops *platform_ops;
|
||||
/** SPI delays */
|
||||
struct no_os_platform_spi_delays platform_delays;
|
||||
/** SPI extra parameters (device specific) */
|
||||
void *extra;
|
||||
/** Parent of the device */
|
||||
struct no_os_spi_desc *parent;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_spi_platform_ops
|
||||
* @brief Structure holding SPI function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_spi_platform_ops {
|
||||
/** SPI initialization function pointer */
|
||||
int32_t (*init)(struct no_os_spi_desc **, const struct no_os_spi_init_param *);
|
||||
/** SPI write/read function pointer */
|
||||
int32_t (*write_and_read)(struct no_os_spi_desc *, uint8_t *, uint16_t);
|
||||
/** Iterate over the spi_msg array and send all messages at once */
|
||||
int32_t (*transfer)(struct no_os_spi_desc *, struct no_os_spi_msg *, uint32_t);
|
||||
/** Iterate over the spi_msg array and send all messages using DMA.
|
||||
* Blocks until the transfer is completed.
|
||||
*/
|
||||
int32_t (*transfer_dma)(struct no_os_spi_desc *, struct no_os_spi_msg *,
|
||||
uint32_t);
|
||||
/** Iterate over the spi_msg array and send all messages using DMA.
|
||||
* Returns immediately after the transfer is started and invokes a
|
||||
* callback once all the messages have been transfered.
|
||||
*/
|
||||
int32_t (*transfer_dma_async)(struct no_os_spi_desc *, struct no_os_spi_msg *,
|
||||
uint32_t, void (*)(void *), void *);
|
||||
/** SPI remove function pointer */
|
||||
int32_t (*remove)(struct no_os_spi_desc *);
|
||||
/** SPI abort function pointer */
|
||||
int32_t (*transfer_abort)(struct no_os_spi_desc *);
|
||||
};
|
||||
|
||||
/* Initialize the SPI communication peripheral. */
|
||||
int32_t no_os_spi_init(struct no_os_spi_desc **desc,
|
||||
const struct no_os_spi_init_param *param);
|
||||
|
||||
/* Free the resources allocated by no_os_spi_init(). */
|
||||
int32_t no_os_spi_remove(struct no_os_spi_desc *desc);
|
||||
|
||||
/* Write and read data to/from SPI. */
|
||||
int32_t no_os_spi_write_and_read(struct no_os_spi_desc *desc,
|
||||
uint8_t *data,
|
||||
uint16_t bytes_number);
|
||||
|
||||
/* Iterate over the spi_msg array and send all messages at once */
|
||||
int32_t no_os_spi_transfer(struct no_os_spi_desc *desc,
|
||||
struct no_os_spi_msg *msgs,
|
||||
uint32_t len);
|
||||
|
||||
/* Transfer a list of messages using DMA. Wait until all transfers are done */
|
||||
int32_t no_os_spi_transfer_dma(struct no_os_spi_desc *desc,
|
||||
struct no_os_spi_msg *msgs,
|
||||
uint32_t len);
|
||||
/*
|
||||
* Transfer a list of messages using DMA. Return once the first one started and
|
||||
* invoke a callback when they are done.
|
||||
*/
|
||||
int32_t no_os_spi_transfer_dma_async(struct no_os_spi_desc *desc,
|
||||
struct no_os_spi_msg *msgs,
|
||||
uint32_t len,
|
||||
void (*callback)(void *),
|
||||
void *ctx);
|
||||
|
||||
/* Abort SPI transfers. */
|
||||
int32_t no_os_spi_transfer_abort(struct no_os_spi_desc *desc);
|
||||
|
||||
/* Initialize SPI bus descriptor*/
|
||||
int32_t no_os_spibus_init(const struct no_os_spi_init_param *param);
|
||||
|
||||
/* Free the resources allocated for SPI bus desc*/
|
||||
void no_os_spibus_remove(uint32_t bus_number);
|
||||
|
||||
|
||||
#endif // _NO_OS_SPI_H_
|
||||
@@ -0,0 +1,125 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_tdm.c
|
||||
* @brief Implementation of the TDM interface
|
||||
* @author Darius Berghe (darius.berghe@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "no_os_tdm.h"
|
||||
#include <stdlib.h>
|
||||
#include "no_os_error.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize the TDM communication peripheral.
|
||||
* @param desc - The TDM descriptor.
|
||||
* @param param - The structure that contains the TDM parameters.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t no_os_tdm_init(struct no_os_tdm_desc **desc,
|
||||
const struct no_os_tdm_init_param *param)
|
||||
{
|
||||
if (!param)
|
||||
return -1;
|
||||
|
||||
if ((param->platform_ops->tdm_ops_init(desc, param)))
|
||||
return -1;
|
||||
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by no_os_tdm_init().
|
||||
* @param desc - The TDM descriptor.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t no_os_tdm_remove(struct no_os_tdm_desc *desc)
|
||||
{
|
||||
return desc->platform_ops->tdm_ops_remove(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read data using the TDM interface
|
||||
* @param desc - The TDM descriptor.
|
||||
* @param data - The buffer to store the received data.
|
||||
* @param nb_samples - Number of samples to read.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t no_os_tdm_read(struct no_os_tdm_desc *desc,
|
||||
void *data,
|
||||
uint16_t nb_samples)
|
||||
{
|
||||
return desc->platform_ops->tdm_ops_read(desc, data, nb_samples);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pause TDM DMA transfer
|
||||
* @param desc - The TDM descriptor.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t no_os_tdm_pause(struct no_os_tdm_desc *desc)
|
||||
{
|
||||
return desc->platform_ops->tdm_ops_pause(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume TDM DMA transfer
|
||||
* @param desc - The TDM descriptor.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t no_os_tdm_resume(struct no_os_tdm_desc *desc)
|
||||
{
|
||||
return desc->platform_ops->tdm_ops_resume(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop TDM DMA transfer
|
||||
* @param desc - The TDM descriptor.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t no_os_tdm_stop(struct no_os_tdm_desc *desc)
|
||||
{
|
||||
return desc->platform_ops->tdm_ops_stop(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write data using the TDM interface
|
||||
* @param desc - The TDM descriptor.
|
||||
* @param data - The buffer with the data to be transmitted.
|
||||
* @param nb_samples - Number of samples to write.
|
||||
* @return 0 in case of success, negative error code otherwise.
|
||||
*/
|
||||
int32_t no_os_tdm_write(struct no_os_tdm_desc *desc,
|
||||
void *data,
|
||||
uint16_t nb_samples)
|
||||
{
|
||||
return desc->platform_ops->tdm_ops_write(desc, data, nb_samples);
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_tdm.h
|
||||
* @brief Header file of TDM Interface
|
||||
* @author Darius Berghe (darius.berghe@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_TDM_H_
|
||||
#define _NO_OS_TDM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* @struct no_os_tdm_platform_ops
|
||||
* @brief Structure holding TDM function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_tdm_platform_ops;
|
||||
|
||||
enum no_os_tdm_mode {
|
||||
NO_OS_TDM_MASTER_TX,
|
||||
NO_OS_TDM_MASTER_RX,
|
||||
NO_OS_TDM_SLAVE_TX,
|
||||
NO_OS_TDM_SLAVE_RX
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_tdm_init_param
|
||||
* @brief Structure holding the parameters for TDM initialization
|
||||
*/
|
||||
struct no_os_tdm_init_param {
|
||||
/** TDM operating mode: master/slave, tx/rx */
|
||||
enum no_os_tdm_mode mode;
|
||||
/** Useful data size in a slot, specified in number of bits */
|
||||
uint8_t data_size;
|
||||
/** Data offset in a slot, specified in number of bits as offset from MSbit */
|
||||
uint8_t data_offset;
|
||||
/** Data ordering (default: msb first) */
|
||||
bool data_lsb_first;
|
||||
/** Number of slots in a frame */
|
||||
uint8_t slots_per_frame;
|
||||
/** Frame sync polarity specifier (default: FS active high) */
|
||||
bool fs_active_low;
|
||||
/** Frame sync active length specified in number of bits */
|
||||
uint8_t fs_active_length;
|
||||
/** Frame sync is normally asserted on first bit of slot 0 of a frame, this specifier allows assertion on last bit of the previous frame */
|
||||
bool fs_lastbit;
|
||||
/** Specify whether data sampling occurs on SCK rising edge (default: on SCK falling edge) */
|
||||
bool rising_edge_sampling;
|
||||
/* IRQ ID */
|
||||
uint32_t irq_id;
|
||||
/** DMA receive complete callback **/
|
||||
void (*rx_complete_callback)(void *rx_arg);
|
||||
/** DMA receive Half complete callback **/
|
||||
void (*rx_half_complete_callback)(void *rx_arg);
|
||||
/** Platform operation function pointers */
|
||||
const struct no_os_tdm_platform_ops *platform_ops;
|
||||
/** TDM extra parameters (platform specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_tdm_desc
|
||||
* @brief Structure holding TDM descriptor.
|
||||
*/
|
||||
struct no_os_tdm_desc {
|
||||
/* IRQ ID */
|
||||
uint32_t irq_id;
|
||||
/** Platform operation function pointers */
|
||||
const struct no_os_tdm_platform_ops *platform_ops;
|
||||
/** Software FIFO. */
|
||||
struct lf256fifo *rx_fifo;
|
||||
/** TDM extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_tdm_platform_ops
|
||||
* @brief Structure holding TDM function pointers that point to the platform
|
||||
* specific function.
|
||||
*/
|
||||
struct no_os_tdm_platform_ops {
|
||||
/** TDM initialization operation function pointer */
|
||||
int32_t (*tdm_ops_init)(struct no_os_tdm_desc **,
|
||||
const struct no_os_tdm_init_param *);
|
||||
/** TDM read operation function pointer */
|
||||
int32_t (*tdm_ops_read)(struct no_os_tdm_desc *, void *, uint16_t);
|
||||
/** TDM write operation function pointer */
|
||||
int32_t (*tdm_ops_write)(struct no_os_tdm_desc *, void *, uint16_t);
|
||||
/** Pause TDM DMA transfer */
|
||||
int32_t (*tdm_ops_pause)(struct no_os_tdm_desc *);
|
||||
/** Resume TDM DMA transfer */
|
||||
int32_t (*tdm_ops_resume)(struct no_os_tdm_desc *);
|
||||
/** Stop TDM DMA transfer */
|
||||
int32_t (*tdm_ops_stop)(struct no_os_tdm_desc *);
|
||||
/** TDM remove operation function pointer */
|
||||
int32_t (*tdm_ops_remove)(struct no_os_tdm_desc *);
|
||||
};
|
||||
|
||||
/* Initialize the TDM communication peripheral. */
|
||||
int32_t no_os_tdm_init(struct no_os_tdm_desc **desc,
|
||||
const struct no_os_tdm_init_param *param);
|
||||
|
||||
/* Free the resources allocated by no_os_tdm_init(). */
|
||||
int32_t no_os_tdm_remove(struct no_os_tdm_desc *desc);
|
||||
|
||||
/* Read data. */
|
||||
int32_t no_os_tdm_read(struct no_os_tdm_desc *desc,
|
||||
void *data,
|
||||
uint16_t bytes_number);
|
||||
|
||||
/* Write data. */
|
||||
int32_t no_os_tdm_write(struct no_os_tdm_desc *desc,
|
||||
void *data,
|
||||
uint16_t bytes_number);
|
||||
|
||||
/* Pause TDM DMA Transfer */
|
||||
int32_t no_os_tdm_pause(struct no_os_tdm_desc *desc);
|
||||
|
||||
/* Resume TDM DMA Transfer */
|
||||
int32_t no_os_tdm_resume(struct no_os_tdm_desc *desc);
|
||||
|
||||
/* Stop TDM DMA Transfer */
|
||||
int32_t no_os_tdm_stop(struct no_os_tdm_desc *desc);
|
||||
|
||||
#endif // _NO_OS_TDM_H_
|
||||
@@ -0,0 +1,213 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_timer.c
|
||||
* @brief Implementation of the timer Interface
|
||||
* @author RBolboac (ramona.bolboaca@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2022(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "no_os_error.h"
|
||||
#include "no_os_timer.h"
|
||||
#include "no_os_mutex.h"
|
||||
|
||||
/**
|
||||
* @brief - TIMER mutex
|
||||
*/
|
||||
static void *timer_mutex_table[TIMER_MAX_TABLE + 1];
|
||||
|
||||
/**
|
||||
* @brief Initialize hardware timer and the handler structure associated with
|
||||
* it.
|
||||
* @param [out] desc - Pointer to the reference of the device handler.
|
||||
* @param [in] param - Initialization structure.
|
||||
* @return 0 in case of success, negative error code otherwise
|
||||
*/
|
||||
int32_t no_os_timer_init(struct no_os_timer_desc **desc,
|
||||
const struct no_os_timer_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!param || !param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->init)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = param->platform_ops->init(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
|
||||
no_os_mutex_init(&timer_mutex_table[param->id]);
|
||||
(*desc)->mutex = timer_mutex_table[param->id];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the memory allocated by timer_init().
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @return 0 in case of success, negative error code otherwise
|
||||
*/
|
||||
int32_t no_os_timer_remove(struct no_os_timer_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->remove)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_remove(desc->mutex);
|
||||
timer_mutex_table[desc->id] = NULL;
|
||||
|
||||
return desc->platform_ops->remove(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start a timer.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @return 0 in case of success, negative error code otherwise
|
||||
*/
|
||||
int32_t no_os_timer_start(struct no_os_timer_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->start)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->start(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop a timer from counting.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @return 0 in case of success, negative error code otherwise
|
||||
*/
|
||||
int32_t no_os_timer_stop(struct no_os_timer_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->stop)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_unlock(desc->mutex);
|
||||
return desc->platform_ops->stop(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the value of the counter register for the timer.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @param [out] counter - Pointer to the counter value.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int32_t no_os_timer_counter_get(struct no_os_timer_desc *desc,
|
||||
uint32_t *counter)
|
||||
{
|
||||
if (!desc || !desc->platform_ops || !counter)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->counter_get)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->counter_get(desc, counter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the timer counter register value.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @param [in] new_val - The new value of the counter register.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int32_t no_os_timer_counter_set(struct no_os_timer_desc *desc, uint32_t new_val)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->counter_set)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->counter_set(desc, new_val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the timer clock frequency.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @param [out] freq_hz - The value in Hz of the timer clock.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int32_t no_os_timer_count_clk_get(struct no_os_timer_desc *desc,
|
||||
uint32_t *freq_hz)
|
||||
{
|
||||
if (!desc || !desc->platform_ops || !freq_hz)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->count_clk_get)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->count_clk_get(desc, freq_hz);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the timer clock frequency.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @param [in] freq_hz - The value in Hz of the new timer clock.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int32_t no_os_timer_count_clk_set(struct no_os_timer_desc *desc,
|
||||
uint32_t freq_hz)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->count_clk_set)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->count_clk_set(desc, freq_hz);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the elapsed time in nsec for the timer.
|
||||
* @param [in] desc - Pointer to the device handler.
|
||||
* @param [in] elapsed_time - The elapsed time in nsec.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int32_t no_os_timer_get_elapsed_time_nsec(struct no_os_timer_desc *desc,
|
||||
uint64_t *elapsed_time)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->get_elapsed_time_nsec)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->get_elapsed_time_nsec(desc, elapsed_time);
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_timer.h
|
||||
* @brief Timer control module header.
|
||||
* @author Andrei Drimbarean (andrei.drimbarean@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _NO_OS_SRC_TIMER_H_
|
||||
#define _NO_OS_SRC_TIMER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define TIMER_MAX_TABLE 4
|
||||
|
||||
/**
|
||||
* @struct no_os_timer_desc
|
||||
* @brief Structure holding timer descriptor
|
||||
*/
|
||||
struct no_os_timer_desc {
|
||||
/** Timer mutex*/
|
||||
void *mutex;
|
||||
/** timer ID */
|
||||
uint16_t id;
|
||||
/** timer count frequency (Hz) */
|
||||
uint32_t freq_hz;
|
||||
/** the number of ticks the timer counts until it resets */
|
||||
uint32_t ticks_count;
|
||||
/** Timer platform operations */
|
||||
const struct no_os_timer_platform_ops *platform_ops;
|
||||
/** timer extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_timer_platform_ops
|
||||
* @brief Structure holding timer function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_timer_platform_ops ;
|
||||
|
||||
/**
|
||||
* @struct no_os_timer_init_param
|
||||
* @brief Structure holding the parameters for timer initialization
|
||||
*/
|
||||
struct no_os_timer_init_param {
|
||||
/** timer ID */
|
||||
uint16_t id;
|
||||
/** timer count frequency (Hz) */
|
||||
uint32_t freq_hz;
|
||||
/** the number of ticks the timer counts until it resets */
|
||||
uint32_t ticks_count;
|
||||
/** Timer platform operations */
|
||||
const struct no_os_timer_platform_ops *platform_ops;
|
||||
/** timer extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_timer_platform_ops
|
||||
* @brief Structure holding timer function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_timer_platform_ops {
|
||||
/** timer initialization function pointer */
|
||||
int32_t (*init)(struct no_os_timer_desc **,
|
||||
const struct no_os_timer_init_param *);
|
||||
/** timer start function pointer */
|
||||
int32_t (*start)(struct no_os_timer_desc *);
|
||||
/** timer stop function pointer */
|
||||
int32_t (*stop)(struct no_os_timer_desc *);
|
||||
/** timer get counter function pointer */
|
||||
int32_t (*counter_get)(struct no_os_timer_desc *, uint32_t *counter);
|
||||
/** timer set counter function pointer */
|
||||
int32_t (*counter_set)(struct no_os_timer_desc *, uint32_t new_val);
|
||||
/** timer get clock frequency function pointer */
|
||||
int32_t (*count_clk_get)(struct no_os_timer_desc *, uint32_t *freq_hz);
|
||||
/** timer set clock frequency function pointer */
|
||||
int32_t (*count_clk_set)(struct no_os_timer_desc *, uint32_t freq_hz);
|
||||
/** timer get elapsed time in nsec */
|
||||
int32_t (*get_elapsed_time_nsec)(struct no_os_timer_desc *,
|
||||
uint64_t *elapsed_time);
|
||||
/** timer remove function pointer */
|
||||
int32_t (*remove)(struct no_os_timer_desc *);
|
||||
};
|
||||
|
||||
/* Initialize hardware timer and the handler structure associated with it. */
|
||||
int32_t no_os_timer_init(struct no_os_timer_desc **desc,
|
||||
const struct no_os_timer_init_param *param);
|
||||
|
||||
/* Free the memory allocated by timer_setup(). */
|
||||
int32_t no_os_timer_remove(struct no_os_timer_desc *desc);
|
||||
|
||||
/* Start a timer. */
|
||||
int32_t no_os_timer_start(struct no_os_timer_desc *desc);
|
||||
|
||||
/* Stop a timer from counting. */
|
||||
int32_t no_os_timer_stop(struct no_os_timer_desc *desc);
|
||||
|
||||
/* Get the value of the counter register for the timer. */
|
||||
int32_t no_os_timer_counter_get(struct no_os_timer_desc *desc,
|
||||
uint32_t *counter);
|
||||
|
||||
/* Set the timer counter register value. */
|
||||
int32_t no_os_timer_counter_set(struct no_os_timer_desc *desc,
|
||||
uint32_t new_val);
|
||||
|
||||
/* Get the timer clock frequency. */
|
||||
int32_t no_os_timer_count_clk_get(struct no_os_timer_desc *desc,
|
||||
uint32_t *freq_hz);
|
||||
|
||||
/* Set the timer clock frequency. */
|
||||
int32_t no_os_timer_count_clk_set(struct no_os_timer_desc *desc,
|
||||
uint32_t freq_hz);
|
||||
|
||||
/* Get the elapsed time in nsec for the timer. */
|
||||
int32_t no_os_timer_get_elapsed_time_nsec(struct no_os_timer_desc *desc,
|
||||
uint64_t *elapsed_time);
|
||||
|
||||
#endif // _NO_OS_SRC_TIMER_H_
|
||||
@@ -0,0 +1,98 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_trng.c
|
||||
* @brief Implementation of the TRNG Interface
|
||||
* @author Antoniu Miclaus (antoniu.miclaus@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2023(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "no_os_trng.h"
|
||||
#include <stdlib.h>
|
||||
#include "no_os_error.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize the TRNG.
|
||||
* @param desc - The TRNG descriptor.
|
||||
* @param param - The structure that contains the TRNG parameters.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int no_os_trng_init(struct no_os_trng_desc **desc,
|
||||
const struct no_os_trng_init_param *param)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!param || !param->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->init)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = param->platform_ops->init(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by no_os_trng_init().
|
||||
* @param desc - The TRNG descriptor.
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int no_os_trng_remove(struct no_os_trng_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->remove)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->remove(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fill buffer with rng data.
|
||||
* @param desc - The TRNG descriptor.
|
||||
* @param buff - Buffer to be filled
|
||||
* @param len - Size of the buffer
|
||||
* @return 0 in case of success, -1 otherwise.
|
||||
*/
|
||||
int no_os_trng_fill_buffer(struct no_os_trng_desc *desc, uint8_t *buff,
|
||||
uint32_t len)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->fill_buffer)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->fill_buffer(desc, buff, len);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_trng.h
|
||||
* @brief Header file of true random number generator
|
||||
* @author Mihail Chindris (mihail.chindris@analog.com)
|
||||
********************************************************************************
|
||||
* @copyright
|
||||
* Copyright 2020(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _NO_OS_TRNG_H_
|
||||
#define _NO_OS_TRNG_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @struct no_os_trng_platform_ops
|
||||
* @brief Structure holding TRNG function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_trng_platform_ops;
|
||||
|
||||
/**
|
||||
* @struct no_os_trng_desc
|
||||
* @brief TRNG Descriptor
|
||||
*/
|
||||
struct no_os_trng_desc {
|
||||
/** Platform ops */
|
||||
const struct no_os_trng_platform_ops *platform_ops;
|
||||
/** Platform specific parameters */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_trng_init_param
|
||||
* @brief Init parameter for TRNG
|
||||
*/
|
||||
struct no_os_trng_init_param {
|
||||
/** Device id */
|
||||
uint32_t dev_id;
|
||||
/** Platform specific parameter */
|
||||
void *extra;
|
||||
/** Platform ops */
|
||||
const struct no_os_trng_platform_ops *platform_ops;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_trng_platform_ops
|
||||
* @brief Structure holding TRNG function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_trng_platform_ops {
|
||||
/** TRNG initialization function pointer */
|
||||
int (*init)(struct no_os_trng_desc **,
|
||||
struct no_os_trng_init_param *);
|
||||
/** Fill buffer with random numbers */
|
||||
int (*fill_buffer)(struct no_os_trng_desc *, uint8_t *, uint32_t);
|
||||
/** TRNG remove function pointer */
|
||||
int (*remove)(struct no_os_trng_desc *);
|
||||
};
|
||||
|
||||
/* Initialize descriptor */
|
||||
int no_os_trng_init(struct no_os_trng_desc **desc,
|
||||
const struct no_os_trng_init_param *param);
|
||||
|
||||
/* Free resources allocated in descriptor */
|
||||
int no_os_trng_remove(struct no_os_trng_desc *desc);
|
||||
|
||||
/* Fill buffer with random numbers */
|
||||
int no_os_trng_fill_buffer(struct no_os_trng_desc *desc, uint8_t *buff,
|
||||
uint32_t len);
|
||||
|
||||
#endif // _NO_OS_TRNG_H_
|
||||
@@ -0,0 +1,220 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_uart.c
|
||||
* @brief Implementation of the UART Interface
|
||||
* @author Ramona Bolboaca (ramona.bolboaca@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2022(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "no_os_uart.h"
|
||||
#include <stdlib.h>
|
||||
#include "no_os_error.h"
|
||||
#include "no_os_mutex.h"
|
||||
#include "no_os_util.h"
|
||||
|
||||
/**
|
||||
* @brief - UART mutex
|
||||
*/
|
||||
static void *uart_mutex_table[UART_MAX_NUMBER + 1];
|
||||
|
||||
/**
|
||||
* @brief Initialize the UART communication peripheral.
|
||||
* @param desc - The UART descriptor.
|
||||
* @param param - The structure that contains the UART parameters.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int32_t no_os_uart_init(struct no_os_uart_desc **desc,
|
||||
struct no_os_uart_init_param *param)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!param || !param->platform_ops
|
||||
|| param->device_id >= NO_OS_ARRAY_SIZE(uart_mutex_table))
|
||||
return -EINVAL;
|
||||
|
||||
if (!param->platform_ops->init)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = param->platform_ops->init(desc, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*desc)->platform_ops = param->platform_ops;
|
||||
|
||||
no_os_mutex_init(&(uart_mutex_table[param->device_id]));
|
||||
(*desc)-> mutex = uart_mutex_table[param->device_id];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the resources allocated by no_os_uart_init().
|
||||
* @param desc - The UART descriptor.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int32_t no_os_uart_remove(struct no_os_uart_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->remove)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_remove(desc->mutex);
|
||||
uart_mutex_table[desc->device_id] = NULL;
|
||||
|
||||
return desc->platform_ops->remove(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if errors occurred on UART.
|
||||
* @param desc - The UART descriptor.
|
||||
* @return number of errors in case of success, error code otherwise.
|
||||
*/
|
||||
uint32_t no_os_uart_get_errors(struct no_os_uart_desc *desc)
|
||||
{
|
||||
if (!desc || !desc->platform_ops)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->get_errors)
|
||||
return -ENOSYS;
|
||||
|
||||
return desc->platform_ops->get_errors(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read data from UART.
|
||||
* @param desc - The UART descriptor.
|
||||
* @param data - The buffer with the received data.
|
||||
* @param bytes_number - Number of bytes to read.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int32_t no_os_uart_read(struct no_os_uart_desc *desc,
|
||||
uint8_t *data,
|
||||
uint32_t bytes_number)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!desc || !desc->platform_ops || !data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->read)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_lock(desc->mutex);
|
||||
ret = desc->platform_ops->read(desc, data, bytes_number);
|
||||
no_os_mutex_unlock(desc->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write to UART.
|
||||
* @param desc - The UART descriptor.
|
||||
* @param data - The buffer with the transmitted data.
|
||||
* @param bytes_number - Number of bytes to write.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int32_t no_os_uart_write(struct no_os_uart_desc *desc,
|
||||
const uint8_t *data,
|
||||
uint32_t bytes_number)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!desc || !desc->platform_ops || !data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->write)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_lock(desc->mutex);
|
||||
ret = desc->platform_ops->write(desc, data, bytes_number);
|
||||
no_os_mutex_unlock(desc->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read data from UART non-blocking.
|
||||
* @param desc - The UART descriptor.
|
||||
* @param data - The buffer with the received data.
|
||||
* @param bytes_number - Number of bytes to read.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int32_t no_os_uart_read_nonblocking(struct no_os_uart_desc *desc,
|
||||
uint8_t *data,
|
||||
uint32_t bytes_number)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!desc || !desc->platform_ops || !data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->read_nonblocking)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_lock(desc->mutex);
|
||||
ret = desc->platform_ops->read_nonblocking(desc, data, bytes_number);
|
||||
no_os_mutex_unlock(desc->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write to UART non-blocking.
|
||||
* @param desc - The UART descriptor.
|
||||
* @param data - The buffer with the transmitted data.
|
||||
* @param bytes_number - Number of bytes to write.
|
||||
* @return 0 in case of success, error code otherwise.
|
||||
*/
|
||||
int32_t no_os_uart_write_nonblocking(struct no_os_uart_desc *desc,
|
||||
const uint8_t *data,
|
||||
uint32_t bytes_number)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (!desc || !desc->platform_ops || !data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!desc->platform_ops->write_nonblocking)
|
||||
return -ENOSYS;
|
||||
|
||||
no_os_mutex_lock(desc->mutex);
|
||||
ret = desc->platform_ops->write_nonblocking(desc, data, bytes_number);
|
||||
no_os_mutex_unlock(desc->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void __attribute__((weak)) no_os_uart_stdio(struct no_os_uart_desc *desc)
|
||||
{
|
||||
/* This can optionally be implemented under drivers/platform.
|
||||
* It does nothing if unimplemented. */
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_uart.h
|
||||
* @brief Header file of UART interface.
|
||||
* @author Cristian Pop (cristian.pop@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_UART_H_
|
||||
#define _NO_OS_UART_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "no_os_lf256fifo.h"
|
||||
|
||||
#define UART_MAX_NUMBER 10
|
||||
|
||||
/**
|
||||
* @enum no_os_uart_size
|
||||
* @brief UART character size (number of data bits) options.
|
||||
*/
|
||||
enum no_os_uart_size {
|
||||
/** 5 data bits */
|
||||
NO_OS_UART_CS_5,
|
||||
/** 6 data bits */
|
||||
NO_OS_UART_CS_6,
|
||||
/** 7 data bits */
|
||||
NO_OS_UART_CS_7,
|
||||
/** 8 data bits */
|
||||
NO_OS_UART_CS_8,
|
||||
/** 9 data bits */
|
||||
NO_OS_UART_CS_9,
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum no_os_uart_parity
|
||||
* @brief UART parity options.
|
||||
*/
|
||||
enum no_os_uart_parity {
|
||||
/** no parity */
|
||||
NO_OS_UART_PAR_NO,
|
||||
/** mark parity */
|
||||
NO_OS_UART_PAR_MARK,
|
||||
/** space parity */
|
||||
NO_OS_UART_PAR_SPACE,
|
||||
/** odd parity */
|
||||
NO_OS_UART_PAR_ODD,
|
||||
/** even parity */
|
||||
NO_OS_UART_PAR_EVEN
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum no_os_uart_stop
|
||||
* @brief UART number of stop bits options.
|
||||
*/
|
||||
enum no_os_uart_stop {
|
||||
/** one stop bit */
|
||||
NO_OS_UART_STOP_1_BIT,
|
||||
/** two stop bits */
|
||||
NO_OS_UART_STOP_2_BIT
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_uart_platform_ops
|
||||
* @brief Structure holding UART function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_uart_platform_ops ;
|
||||
|
||||
/**
|
||||
* @struct no_os_uart_init_param
|
||||
* @brief Structure holding the parameters for UART initialization
|
||||
*/
|
||||
struct no_os_uart_init_param {
|
||||
/** UART Device ID */
|
||||
uint8_t device_id;
|
||||
/** UART Interrupt ID */
|
||||
uint32_t irq_id;
|
||||
/** If set, the reception is interrupt driven. */
|
||||
bool asynchronous_rx;
|
||||
/** UART Baud Rate */
|
||||
uint32_t baud_rate;
|
||||
/** UART number of data bits */
|
||||
enum no_os_uart_size size;
|
||||
/** UART parity */
|
||||
enum no_os_uart_parity parity;
|
||||
/** UART number of stop bits */
|
||||
enum no_os_uart_stop stop;
|
||||
const struct no_os_uart_platform_ops *platform_ops;
|
||||
/** UART extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_uart_desc
|
||||
* @brief Stucture holding the UART descriptor.
|
||||
*/
|
||||
struct no_os_uart_desc {
|
||||
/** UART mutex*/
|
||||
void *mutex;
|
||||
/** UART Device ID */
|
||||
uint8_t device_id;
|
||||
/** UART Interrupt ID */
|
||||
uint32_t irq_id;
|
||||
/** Software FIFO. */
|
||||
struct lf256fifo *rx_fifo;
|
||||
/** UART Baud Rate */
|
||||
uint32_t baud_rate;
|
||||
const struct no_os_uart_platform_ops *platform_ops;
|
||||
/** UART extra parameters (device specific) */
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct no_os_uart_platform_ops
|
||||
* @brief Structure holding UART function pointers that point to the platform
|
||||
* specific function
|
||||
*/
|
||||
struct no_os_uart_platform_ops {
|
||||
/** UART initialization function pointer */
|
||||
int32_t (*init)(struct no_os_uart_desc **, struct no_os_uart_init_param *);
|
||||
/** UART read function pointer */
|
||||
int32_t (*read)(struct no_os_uart_desc *, uint8_t *, uint32_t);
|
||||
/** UART write function pointer */
|
||||
int32_t (*write)(struct no_os_uart_desc *, const uint8_t *, uint32_t);
|
||||
/** UART read non-blocking function pointer */
|
||||
int32_t (*read_nonblocking)(struct no_os_uart_desc *, uint8_t *, uint32_t);
|
||||
/** UART wrote non-blocking function pointer */
|
||||
int32_t (*write_nonblocking)(struct no_os_uart_desc *, const uint8_t *,
|
||||
uint32_t);
|
||||
/** UART remove function pointer */
|
||||
int32_t (*remove)(struct no_os_uart_desc *);
|
||||
/** UART get errors function pointer */
|
||||
uint32_t (*get_errors)(struct no_os_uart_desc *);
|
||||
};
|
||||
|
||||
/* Read data from UART. Blocking function */
|
||||
int32_t no_os_uart_read(struct no_os_uart_desc *desc, uint8_t *data,
|
||||
uint32_t bytes_number);
|
||||
|
||||
/* Write data to UART. Blocking function */
|
||||
int32_t no_os_uart_write(struct no_os_uart_desc *desc, const uint8_t *data,
|
||||
uint32_t bytes_number);
|
||||
|
||||
/* Read data from UART. Non blocking function */
|
||||
int32_t no_os_uart_read_nonblocking(struct no_os_uart_desc *desc, uint8_t *data,
|
||||
uint32_t bytes_number);
|
||||
|
||||
/* Write data to UART. Non blocking function*/
|
||||
int32_t no_os_uart_write_nonblocking(struct no_os_uart_desc *desc,
|
||||
const uint8_t *data,
|
||||
uint32_t bytes_number);
|
||||
|
||||
/* Initialize the UART communication peripheral. */
|
||||
int32_t no_os_uart_init(struct no_os_uart_desc **desc,
|
||||
struct no_os_uart_init_param *param);
|
||||
|
||||
/* Free the resources allocated by no_os_uart_init(). */
|
||||
int32_t no_os_uart_remove(struct no_os_uart_desc *desc);
|
||||
|
||||
/* Check if UART errors occurred. */
|
||||
uint32_t no_os_uart_get_errors(struct no_os_uart_desc *desc);
|
||||
|
||||
/* Make stdio to use this UART. */
|
||||
void no_os_uart_stdio(struct no_os_uart_desc *desc);
|
||||
|
||||
#endif // _NO_OS_UART_H_
|
||||
@@ -0,0 +1,83 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_units.h
|
||||
* @brief Header file of Units
|
||||
* @author Antoniu Miclaus (antoniu.miclaus@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2022(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_UNITS_H_
|
||||
#define _NO_OS_UNITS_H_
|
||||
|
||||
#define PETA 1000000000000000ULL
|
||||
#define TERA 1000000000000ULL
|
||||
#define GIGA 1000000000UL
|
||||
#define MEGA 1000000UL
|
||||
#define KILO 1000UL
|
||||
#define HECTO 100UL
|
||||
#define DECA 10UL
|
||||
#define DECI 10UL
|
||||
#define CENTI 100UL
|
||||
#define MILLI 1000UL
|
||||
#define MICRO 1000000UL
|
||||
#define NANO 1000000000UL
|
||||
#define PICO 1000000000000ULL
|
||||
#define FEMTO 1000000000000000ULL
|
||||
|
||||
#define HZ_PER_KHZ 1000UL
|
||||
#define KHZ_PER_MHZ 1000UL
|
||||
#define HZ_PER_MHZ 1000000UL
|
||||
|
||||
#define MILLIVOLT_PER_VOLT 1000UL
|
||||
#define MICROVOLT_PER_VOLT 1000000UL
|
||||
#define NANOVOLT_PER_VOLT 1000000000ULL
|
||||
|
||||
#define MILLIAMPER_PER_AMPER 1000UL
|
||||
#define MICROAMPER_PER_MILLIAMPER 1000UL
|
||||
#define MICROAMPER_PER_AMPER 1000000UL
|
||||
#define NANOAMPER_PER_AMPER 1000000000ULL
|
||||
|
||||
#define MILLIWATT_PER_WATT 1000UL
|
||||
#define MICROWATT_PER_MILLIWATT 1000UL
|
||||
#define MICROWATT_PER_WATT 1000000UL
|
||||
|
||||
#define MILLIDEGREE_PER_DEGREE 1000UL
|
||||
|
||||
/* Returns the given value converted from degree to rad */
|
||||
#define DEGREE_TO_RAD(deg) (((deg) * 314159ULL + 9000000ULL) / 18000000ULL)
|
||||
|
||||
/* Returns the given value converted from rad to degree */
|
||||
#define RAD_TO_DEGREE(rad) \
|
||||
(((rad) * 18000000ULL + 314159ULL / 2) / 314159ULL)
|
||||
|
||||
/* Returns the given value converted from g to meter / second**2 */
|
||||
#define G_TO_M_S_2(g) ((g) * 980665ULL / 100000ULL)
|
||||
|
||||
/* Returns the given value converted from meter / second**2 to g */
|
||||
#define M_S_2_TO_G(ms2) (((ms2) * 100000ULL + 980665ULL / 2) / 980665ULL)
|
||||
|
||||
#endif // _NO_OS_UNITS_H_
|
||||
@@ -0,0 +1,568 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_util.c
|
||||
* @brief Implementation of utility functions.
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2018(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "no_os_util.h"
|
||||
#include "errno.h"
|
||||
extern int no_os_test_bit(int pos, const volatile void * addr);
|
||||
|
||||
/**
|
||||
* Find first set bit in word.
|
||||
*/
|
||||
uint32_t no_os_find_first_set_bit(uint32_t word)
|
||||
{
|
||||
uint32_t first_set_bit = 0;
|
||||
|
||||
while (word) {
|
||||
if (word & 0x1)
|
||||
return first_set_bit;
|
||||
word >>= 1;
|
||||
first_set_bit ++;
|
||||
}
|
||||
|
||||
return 32;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find first set bit in word.
|
||||
*/
|
||||
uint64_t no_os_find_first_set_bit_u64(uint64_t word)
|
||||
{
|
||||
uint64_t first_set_bit = 0;
|
||||
|
||||
while (word) {
|
||||
if (word & 0x1)
|
||||
return first_set_bit;
|
||||
word >>= 1;
|
||||
first_set_bit ++;
|
||||
}
|
||||
|
||||
return 64;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find last set bit in word.
|
||||
*/
|
||||
uint32_t no_os_find_last_set_bit(uint32_t word)
|
||||
{
|
||||
uint32_t bit = 0;
|
||||
uint32_t last_set_bit = 32;
|
||||
|
||||
while (word) {
|
||||
if (word & 0x1)
|
||||
last_set_bit = bit;
|
||||
word >>= 1;
|
||||
bit ++;
|
||||
}
|
||||
|
||||
return last_set_bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate the closest element in an array.
|
||||
*/
|
||||
uint32_t no_os_find_closest(int32_t val,
|
||||
const int32_t *array,
|
||||
uint32_t size)
|
||||
{
|
||||
int32_t diff = abs(array[0] - val);
|
||||
uint32_t ret = 0;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 1; i < size; i++) {
|
||||
if (abs(array[i] - val) < diff) {
|
||||
diff = abs(array[i] - val);
|
||||
ret = i;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift the value and apply the specified mask.
|
||||
*/
|
||||
uint32_t no_os_field_prep(uint32_t mask, uint32_t val)
|
||||
{
|
||||
return (val << no_os_find_first_set_bit(mask)) & mask;
|
||||
}
|
||||
|
||||
uint64_t no_os_field_prep_u64(uint64_t mask, uint64_t val)
|
||||
{
|
||||
return (val << no_os_find_first_set_bit_u64(mask)) & mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a field specified by a mask from a word.
|
||||
*/
|
||||
uint32_t no_os_field_get(uint32_t mask, uint32_t word)
|
||||
{
|
||||
return (word & mask) >> no_os_find_first_set_bit(mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce the maximum value representable by a field
|
||||
*/
|
||||
uint32_t no_os_field_max(uint32_t mask)
|
||||
{
|
||||
// Find the first set bit to determine the shift position
|
||||
uint32_t first_set_bit = no_os_find_first_set_bit(mask);
|
||||
|
||||
// Shift the mask to the right by the position of the first set bit
|
||||
uint32_t shifted_mask = mask >> first_set_bit;
|
||||
|
||||
return shifted_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce the maximum value representable by a field
|
||||
*/
|
||||
uint64_t no_os_field_max_u64(uint64_t mask)
|
||||
{
|
||||
// Find the first set bit to determine the shift position
|
||||
uint64_t first_set_bit = no_os_find_first_set_bit_u64(mask);
|
||||
|
||||
// Shift the mask to the right by the position of the first set bit
|
||||
uint64_t shifted_mask = mask >> first_set_bit;
|
||||
|
||||
return shifted_mask;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log base 2 of the given number.
|
||||
*/
|
||||
int32_t no_os_log_base_2(uint32_t x)
|
||||
{
|
||||
return no_os_find_last_set_bit(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find greatest common divisor of the given two numbers.
|
||||
*/
|
||||
uint32_t no_os_greatest_common_divisor(uint32_t a,
|
||||
uint32_t b)
|
||||
{
|
||||
uint32_t div;
|
||||
|
||||
if ((a == 0) || (b == 0))
|
||||
return no_os_max(a, b);
|
||||
|
||||
while (b != 0) {
|
||||
div = a % b;
|
||||
a = b;
|
||||
b = div;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
uint64_t no_os_greatest_common_divisor_u64(uint64_t a,
|
||||
uint64_t b)
|
||||
{
|
||||
uint64_t div;
|
||||
|
||||
if ((a == 0) || (b == 0))
|
||||
return no_os_max(a, b);
|
||||
|
||||
while (b != 0) {
|
||||
div = a % b;
|
||||
a = b;
|
||||
b = div;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find lowest common multiple of the given two numbers.
|
||||
*/
|
||||
uint32_t no_os_lowest_common_multiple(uint32_t a, uint32_t b)
|
||||
{
|
||||
if (a && b)
|
||||
return (a / no_os_greatest_common_divisor(a, b)) * b;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate best rational approximation for a given fraction.
|
||||
*/
|
||||
void no_os_rational_best_approximation(uint32_t given_numerator,
|
||||
uint32_t given_denominator,
|
||||
uint32_t max_numerator,
|
||||
uint32_t max_denominator,
|
||||
uint32_t *best_numerator,
|
||||
uint32_t *best_denominator)
|
||||
{
|
||||
uint32_t gcd;
|
||||
|
||||
gcd = no_os_greatest_common_divisor(given_numerator, given_denominator);
|
||||
|
||||
*best_numerator = given_numerator / gcd;
|
||||
*best_denominator = given_denominator / gcd;
|
||||
|
||||
if ((*best_numerator > max_numerator) ||
|
||||
(*best_denominator > max_denominator)) {
|
||||
*best_numerator = 0;
|
||||
*best_denominator = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void no_os_rational_best_approximation_u64(uint64_t given_numerator,
|
||||
uint64_t given_denominator,
|
||||
uint64_t max_numerator,
|
||||
uint64_t max_denominator,
|
||||
uint64_t *best_numerator,
|
||||
uint64_t *best_denominator)
|
||||
{
|
||||
uint64_t gcd;
|
||||
|
||||
gcd = no_os_greatest_common_divisor_u64(given_numerator, given_denominator);
|
||||
|
||||
*best_numerator = given_numerator / gcd;
|
||||
*best_denominator = given_denominator / gcd;
|
||||
|
||||
if ((*best_numerator > max_numerator) ||
|
||||
(*best_denominator > max_denominator)) {
|
||||
*best_numerator = 0;
|
||||
*best_denominator = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the number of set bits (8-bit size).
|
||||
*/
|
||||
unsigned int no_os_hweight8(uint8_t word)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
|
||||
while (word) {
|
||||
if (word & 0x1)
|
||||
count++;
|
||||
word >>= 1;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the number of set bits (16-bit size).
|
||||
*/
|
||||
unsigned int no_os_hweight16(uint16_t word)
|
||||
{
|
||||
return no_os_hweight8(word >> 8) +
|
||||
no_os_hweight8(word);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the number of set bits (32-bit size).
|
||||
*/
|
||||
unsigned int no_os_hweight32(uint32_t word)
|
||||
{
|
||||
return no_os_hweight16(word >> 16) +
|
||||
no_os_hweight16(word);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the quotient and the remainder of an integer division.
|
||||
*/
|
||||
uint64_t no_os_do_div(uint64_t* n,
|
||||
uint64_t base)
|
||||
{
|
||||
uint64_t mod = 0;
|
||||
|
||||
mod = *n % base;
|
||||
*n = *n / base;
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsigned 64bit divide with 64bit divisor and remainder
|
||||
*/
|
||||
uint64_t no_os_div64_u64_rem(uint64_t dividend, uint64_t divisor,
|
||||
uint64_t *remainder)
|
||||
{
|
||||
*remainder = dividend % divisor;
|
||||
|
||||
return dividend / divisor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsigned 64bit divide with 32bit divisor with remainder
|
||||
*/
|
||||
uint64_t no_os_div_u64_rem(uint64_t dividend, uint32_t divisor,
|
||||
uint32_t *remainder)
|
||||
{
|
||||
*remainder = no_os_do_div(÷nd, divisor);
|
||||
|
||||
return dividend;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signed 64bit divide with 32bit divisor with remainder
|
||||
*/
|
||||
int64_t no_os_div_s64_rem(int64_t dividend, int32_t divisor, int32_t *remainder)
|
||||
{
|
||||
*remainder = dividend % divisor;
|
||||
return dividend / divisor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsigned 64bit divide with 32bit divisor
|
||||
*/
|
||||
uint64_t no_os_div_u64(uint64_t dividend, uint32_t divisor)
|
||||
{
|
||||
uint32_t remainder;
|
||||
|
||||
return no_os_div_u64_rem(dividend, divisor, &remainder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Signed 64bit divide with 32bit divisor
|
||||
*/
|
||||
int64_t no_os_div_s64(int64_t dividend, int32_t divisor)
|
||||
{
|
||||
int32_t remainder;
|
||||
return no_os_div_s64_rem(dividend, divisor, &remainder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts from string to int32_t
|
||||
* @param *str
|
||||
* @return int32_t
|
||||
*/
|
||||
int32_t no_os_str_to_int32(const char *str)
|
||||
{
|
||||
char *end;
|
||||
int32_t value = strtol(str, &end, 0);
|
||||
|
||||
if (end == str)
|
||||
return -EINVAL;
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts from string to uint32_t
|
||||
* @param *str
|
||||
* @return uint32_t
|
||||
*/
|
||||
uint32_t no_os_str_to_uint32(const char *str)
|
||||
{
|
||||
char *end;
|
||||
uint32_t value = strtoul(str, &end, 0);
|
||||
|
||||
if (end == str)
|
||||
return -EINVAL;
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
void no_os_put_unaligned_be16(uint16_t val, uint8_t *buf)
|
||||
{
|
||||
buf[1] = val & 0xFF;
|
||||
buf[0] = val >> 8;
|
||||
}
|
||||
|
||||
uint16_t no_os_get_unaligned_be16(uint8_t *buf)
|
||||
{
|
||||
return buf[1] | ((uint16_t)buf[0] << 8);
|
||||
}
|
||||
|
||||
void no_os_put_unaligned_le16(uint16_t val, uint8_t *buf)
|
||||
{
|
||||
buf[0] = val & 0xFF;
|
||||
buf[1] = val >> 8;
|
||||
}
|
||||
|
||||
uint16_t no_os_get_unaligned_le16(uint8_t *buf)
|
||||
{
|
||||
return buf[0] | ((uint16_t)buf[1] << 8);
|
||||
}
|
||||
|
||||
void no_os_put_unaligned_be24(uint32_t val, uint8_t *buf)
|
||||
{
|
||||
buf[2] = val & 0xFF;
|
||||
buf[1] = (val >> 8) & 0xFF;
|
||||
buf[0] = val >> 16;
|
||||
}
|
||||
|
||||
uint32_t no_os_get_unaligned_be24(uint8_t *buf)
|
||||
{
|
||||
return buf[2] | ((uint16_t)buf[1] << 8) | ((uint32_t)buf[0] << 16);
|
||||
}
|
||||
|
||||
void no_os_put_unaligned_le24(uint32_t val, uint8_t *buf)
|
||||
{
|
||||
buf[0] = val & 0xFF;
|
||||
buf[1] = (val >> 8) & 0xFF;
|
||||
buf[2] = val >> 16;
|
||||
}
|
||||
|
||||
uint32_t no_os_get_unaligned_le24(uint8_t *buf)
|
||||
{
|
||||
return buf[0] | ((uint16_t)buf[1] << 8) | ((uint32_t)buf[2] << 16);
|
||||
}
|
||||
|
||||
void no_os_put_unaligned_be32(uint32_t val, uint8_t *buf)
|
||||
{
|
||||
buf[3] = val & 0xFF;
|
||||
buf[2] = (val >> 8) & 0xFF;
|
||||
buf[1] = (val >> 16) & 0xFF;
|
||||
buf[0] = val >> 24;
|
||||
}
|
||||
|
||||
uint32_t no_os_get_unaligned_be32(uint8_t *buf)
|
||||
{
|
||||
return buf[3] | ((uint16_t)buf[2] << 8) | ((uint32_t)buf[1] << 16)
|
||||
| ((uint32_t)buf[0] << 24);
|
||||
}
|
||||
|
||||
void no_os_put_unaligned_le32(uint32_t val, uint8_t *buf)
|
||||
{
|
||||
buf[0] = val & 0xFF;
|
||||
buf[1] = (val >> 8) & 0xFF;
|
||||
buf[2] = (val >> 16) & 0xFF;
|
||||
buf[3] = val >> 24;
|
||||
}
|
||||
|
||||
uint32_t no_os_get_unaligned_le32(uint8_t *buf)
|
||||
{
|
||||
return buf[0] | ((uint16_t)buf[1] << 8) | ((uint32_t)buf[2] << 16)
|
||||
| ((uint32_t)buf[3] << 24);
|
||||
}
|
||||
|
||||
int16_t no_os_sign_extend16(uint16_t value, int index)
|
||||
{
|
||||
uint8_t shift = 15 - index;
|
||||
return (int16_t)(value << shift) >> shift;
|
||||
}
|
||||
|
||||
int32_t no_os_sign_extend32(uint32_t value, int index)
|
||||
{
|
||||
uint8_t shift = 31 - index;
|
||||
return (int32_t)(value << shift) >> shift;
|
||||
}
|
||||
|
||||
uint64_t no_os_mul_u32_u32(uint32_t a, uint32_t b)
|
||||
{
|
||||
return (uint64_t)a * b;
|
||||
}
|
||||
|
||||
uint64_t no_os_mul_u64_u32_shr(uint64_t a, uint32_t mul, unsigned int shift)
|
||||
{
|
||||
uint32_t ah, al;
|
||||
uint64_t ret;
|
||||
|
||||
al = a;
|
||||
ah = a >> 32;
|
||||
|
||||
ret = no_os_mul_u32_u32(al, mul) >> shift;
|
||||
if (ah)
|
||||
ret += no_os_mul_u32_u32(ah, mul) << (32 - shift);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t no_os_mul_u64_u32_div(uint64_t a, uint32_t mul, uint32_t divisor)
|
||||
{
|
||||
int i;
|
||||
uint64_t low, high, temp, rem;
|
||||
uint32_t a_high = a >> 32;
|
||||
uint32_t a_low = a & 0xFFFFFFFF;
|
||||
uint64_t result = 0;
|
||||
uint64_t low_low = no_os_mul_u32_u32(a_low, mul);
|
||||
uint64_t high_low = no_os_mul_u32_u32(a_high, mul);
|
||||
|
||||
low = low_low + ((high_low & 0xFFFFFFFF) << 32);
|
||||
high = (high_low >> 32) + (low_low >> 32);
|
||||
|
||||
rem = high;
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
/* Shift remainder left and add the next bit from low */
|
||||
rem = (rem << 1) | (low >> 63);
|
||||
low <<= 1;
|
||||
|
||||
/* Compare the remainder with the divisor */
|
||||
if (rem >= divisor) {
|
||||
rem -= divisor;
|
||||
temp = (uint64_t)1 << (63 - i);
|
||||
result |= temp;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check big endianess of the host processor.
|
||||
* @return Big endianess status (true/false)
|
||||
*/
|
||||
bool no_os_is_big_endian(void)
|
||||
{
|
||||
uint16_t a = 0x0100;
|
||||
return (bool) * (uint8_t *)&a;
|
||||
}
|
||||
|
||||
/* @brief Swap bytes in a buffer with a given step
|
||||
* Swap with step of 2:
|
||||
* AA BB CC DD EE FF 00 11 becomes
|
||||
* BB AA DD CC FF EE 11 00
|
||||
* Swap with step of 3:
|
||||
* AA BB CC DD EE FF 00 11 22 becomes
|
||||
* CC BB AA FF EE DD 22 11 00
|
||||
* etc.
|
||||
* @param buf - Input buffer to be swapped.
|
||||
* @param bytes - Number of bytes.
|
||||
* @param step - Number of steps.
|
||||
* @return None
|
||||
*/
|
||||
void no_os_memswap64(void *buf, uint32_t bytes, uint32_t step)
|
||||
{
|
||||
uint8_t * p = buf;
|
||||
uint32_t i, j;
|
||||
uint8_t temp[8];
|
||||
|
||||
if (step < 2 || step > 8 || bytes < step || bytes % step != 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < bytes; i += step) {
|
||||
memcpy(temp, p, step);
|
||||
for (j = step; j > 0; j--) {
|
||||
*p++ = temp[j - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
/***************************************************************************//**
|
||||
* @file no_os_util.h
|
||||
* @brief Header file of utility functions.
|
||||
* @author DBogdan (dragos.bogdan@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2018(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef _NO_OS_UTIL_H_
|
||||
#define _NO_OS_UTIL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#define NO_OS_BIT(x) (1 << (x))
|
||||
|
||||
#define NO_OS_BIT_ULL(x) ((uint64_t) 1 << (x))
|
||||
|
||||
#define NO_OS_ARRAY_SIZE(x) \
|
||||
(sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
#define NO_OS_DIV_ROUND_UP(x,y) \
|
||||
(((x) + (y) - 1) / (y))
|
||||
#define NO_OS_DIV_ROUND_CLOSEST(x, y) \
|
||||
(((x) + (y) / 2) / (y))
|
||||
#define NO_OS_DIV_ROUND_CLOSEST_ULL(x, y) \
|
||||
NO_OS_DIV_ROUND_CLOSEST(x, y)
|
||||
|
||||
#define no_os_min(x, y) \
|
||||
(((x) < (y)) ? (x) : (y))
|
||||
#define no_os_min_t(type, x, y) \
|
||||
(type)no_os_min((type)(x), (type)(y))
|
||||
|
||||
#define no_os_max(x, y) \
|
||||
(((x) > (y)) ? (x) : (y))
|
||||
#define no_os_max_t(type, x, y) \
|
||||
(type)no_os_max((type)(x), (type)(y))
|
||||
|
||||
#define no_os_clamp(val, min_val, max_val) \
|
||||
(no_os_max(no_os_min((val), (max_val)), (min_val)))
|
||||
#define no_os_clamp_t(type, val, min_val, max_val) \
|
||||
(type)no_os_clamp((type)(val), (type)(min_val), (type)(max_val))
|
||||
|
||||
#define no_os_swap(x, y) \
|
||||
{typeof(x) _tmp_ = (x); (x) = (y); (y) = _tmp_;}
|
||||
|
||||
#define no_os_round_up(x,y) \
|
||||
(((x)+(y)-1)/(y))
|
||||
|
||||
#define NO_OS_BITS_PER_LONG 32
|
||||
|
||||
#define NO_OS_GENMASK(h, l) ({ \
|
||||
uint32_t t = (uint32_t)(~0UL); \
|
||||
t = t << (NO_OS_BITS_PER_LONG - (h - l + 1)); \
|
||||
t = t >> (NO_OS_BITS_PER_LONG - (h + 1)); \
|
||||
t; \
|
||||
})
|
||||
#define NO_OS_GENMASK_ULL(h, l) ({ \
|
||||
unsigned long long t = (unsigned long long)(~0ULL); \
|
||||
t = t << (64 - (h - l + 1)); \
|
||||
t = t >> (64 - (h + 1)); \
|
||||
t; \
|
||||
})
|
||||
|
||||
#define no_os_bswap_constant_32(x) \
|
||||
((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
|
||||
(((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
|
||||
|
||||
#define no_os_bswap_constant_16(x) ((((x) & (uint16_t)0xff00) >> 8) | \
|
||||
(((x) & (uint16_t)0x00ff) << 8))
|
||||
|
||||
#define no_os_bit_swap_constant_8(x) \
|
||||
((((x) & 0x80) >> 7) | \
|
||||
(((x) & 0x40) >> 5) | \
|
||||
(((x) & 0x20) >> 3) | \
|
||||
(((x) & 0x10) >> 1) | \
|
||||
(((x) & 0x08) << 1) | \
|
||||
(((x) & 0x04) << 3) | \
|
||||
(((x) & 0x02) << 5) | \
|
||||
(((x) & 0x01) << 7))
|
||||
|
||||
#define NO_OS_U16_MAX ((uint16_t)~0U)
|
||||
#define NO_OS_S16_MAX ((int16_t)(NO_OS_U16_MAX>>1))
|
||||
|
||||
#define NO_OS_DIV_U64(x, y) (x / y)
|
||||
|
||||
#define NO_OS_UNUSED_PARAM(x) ((void)x)
|
||||
|
||||
#define no_os_shift_right(x, s) ((x) < 0 ? -(-(x) >> (s)) : (x) >> (s))
|
||||
|
||||
#define no_os_align(x, align) (((x) + ((typeof(x))(align) - 1)) & ~((typeof(x))(align) - 1))
|
||||
|
||||
#define no_os_bcd2bin(x) (((x) & 0x0f) + ((x) >> 4) * 10)
|
||||
#define no_os_bin2bcd(x) ((((x) / 10) << 4) + (x) % 10)
|
||||
|
||||
#define NO_OS_CONTAINER_OF(ptr, type, name) ((type *)((char *)(ptr) - offsetof(type, name)))
|
||||
|
||||
/* Check if bit set */
|
||||
inline int no_os_test_bit(int pos, const volatile void * addr)
|
||||
{
|
||||
return (((const int *)addr)[pos / 32] >> pos) & 1UL;
|
||||
}
|
||||
|
||||
/* Find first set bit in word. */
|
||||
uint32_t no_os_find_first_set_bit(uint32_t word);
|
||||
uint64_t no_os_find_first_set_bit_u64(uint64_t word);
|
||||
/* Find last set bit in word. */
|
||||
uint32_t no_os_find_last_set_bit(uint32_t word);
|
||||
/* Locate the closest element in an array. */
|
||||
uint32_t no_os_find_closest(int32_t val,
|
||||
const int32_t *array,
|
||||
uint32_t size);
|
||||
/* Shift the value and apply the specified mask. */
|
||||
uint32_t no_os_field_prep(uint32_t mask, uint32_t val);
|
||||
uint64_t no_os_field_prep_u64(uint64_t mask, uint64_t val);
|
||||
/* Get a field specified by a mask from a word. */
|
||||
uint32_t no_os_field_get(uint32_t mask, uint32_t word);
|
||||
/* Produce the maximum value representable by a field */
|
||||
uint32_t no_os_field_max(uint32_t mask);
|
||||
uint64_t no_os_field_max_u64(uint64_t mask);
|
||||
|
||||
/* Log base 2 of the given number. */
|
||||
int32_t no_os_log_base_2(uint32_t x);
|
||||
/* Find greatest common divisor of the given two numbers. */
|
||||
uint32_t no_os_greatest_common_divisor(uint32_t a,
|
||||
uint32_t b);
|
||||
uint64_t no_os_greatest_common_divisor_u64(uint64_t a,
|
||||
uint64_t b);
|
||||
/* Find lowest common multiple of the given two numbers. */
|
||||
uint32_t no_os_lowest_common_multiple(uint32_t a, uint32_t b);
|
||||
/* Calculate best rational approximation for a given fraction. */
|
||||
void no_os_rational_best_approximation(uint32_t given_numerator,
|
||||
uint32_t given_denominator,
|
||||
uint32_t max_numerator,
|
||||
uint32_t max_denominator,
|
||||
uint32_t *best_numerator,
|
||||
uint32_t *best_denominator);
|
||||
void no_os_rational_best_approximation_u64(uint64_t given_numerator,
|
||||
uint64_t given_denominator,
|
||||
uint64_t max_numerator,
|
||||
uint64_t max_denominator,
|
||||
uint64_t *best_numerator,
|
||||
uint64_t *best_denominator);
|
||||
/* Calculate the number of set bits (8-bit size). */
|
||||
unsigned int no_os_hweight8(uint8_t word);
|
||||
/* Calculate the number of set bits (16-bit size). */
|
||||
unsigned int no_os_hweight16(uint16_t word);
|
||||
/* Calculate the number of set bits (32-bit size). */
|
||||
unsigned int no_os_hweight32(uint32_t word);
|
||||
/* Calculate the quotient and the remainder of an integer division. */
|
||||
uint64_t no_os_do_div(uint64_t* n,
|
||||
uint64_t base);
|
||||
/* Unsigned 64bit divide with 64bit divisor and remainder */
|
||||
uint64_t no_os_div64_u64_rem(uint64_t dividend, uint64_t divisor,
|
||||
uint64_t *remainder);
|
||||
/* Unsigned 64bit divide with 32bit divisor with remainder */
|
||||
uint64_t no_os_div_u64_rem(uint64_t dividend, uint32_t divisor,
|
||||
uint32_t *remainder);
|
||||
int64_t no_os_div_s64_rem(int64_t dividend, int32_t divisor,
|
||||
int32_t *remainder);
|
||||
/* Unsigned 64bit divide with 32bit divisor */
|
||||
uint64_t no_os_div_u64(uint64_t dividend, uint32_t divisor);
|
||||
int64_t no_os_div_s64(int64_t dividend, int32_t divisor);
|
||||
/* Converts from string to int32_t */
|
||||
int32_t no_os_str_to_int32(const char *str);
|
||||
/* Converts from string to uint32_t */
|
||||
uint32_t no_os_str_to_uint32(const char *str);
|
||||
|
||||
void no_os_put_unaligned_be16(uint16_t val, uint8_t *buf);
|
||||
uint16_t no_os_get_unaligned_be16(uint8_t *buf);
|
||||
void no_os_put_unaligned_le16(uint16_t val, uint8_t *buf);
|
||||
uint16_t no_os_get_unaligned_le16(uint8_t *buf);
|
||||
void no_os_put_unaligned_be24(uint32_t val, uint8_t *buf);
|
||||
uint32_t no_os_get_unaligned_be24(uint8_t *buf);
|
||||
void no_os_put_unaligned_le24(uint32_t val, uint8_t *buf);
|
||||
uint32_t no_os_get_unaligned_le24(uint8_t *buf);
|
||||
void no_os_put_unaligned_be32(uint32_t val, uint8_t *buf);
|
||||
uint32_t no_os_get_unaligned_be32(uint8_t *buf);
|
||||
void no_os_put_unaligned_le32(uint32_t val, uint8_t *buf);
|
||||
uint32_t no_os_get_unaligned_le32(uint8_t *buf);
|
||||
|
||||
int16_t no_os_sign_extend16(uint16_t value, int index);
|
||||
int32_t no_os_sign_extend32(uint32_t value, int index);
|
||||
uint64_t no_os_mul_u32_u32(uint32_t a, uint32_t b);
|
||||
uint64_t no_os_mul_u64_u32_shr(uint64_t a, uint32_t mul, unsigned int shift);
|
||||
uint64_t no_os_mul_u64_u32_div(uint64_t a, uint32_t mul, uint32_t divisor);
|
||||
|
||||
bool no_os_is_big_endian(void);
|
||||
void no_os_memswap64(void *buf, uint32_t bytes, uint32_t step);
|
||||
|
||||
#endif // _NO_OS_UTIL_H_
|
||||
@@ -0,0 +1,42 @@
|
||||
/***************************************************************************//**
|
||||
* @file parameters.c
|
||||
* @brief Definition of STM32 platform data used by adf4382 project.
|
||||
* @author CHegbeli (ciprian.hegbeli@analog.com)
|
||||
********************************************************************************
|
||||
* Copyright 2023(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
#include "parameters.h"
|
||||
|
||||
struct stm32_uart_init_param adf4382_uart_extra_ip = {
|
||||
.huart = &huart2,
|
||||
};
|
||||
|
||||
struct stm32_spi_init_param adf4382_spi_extra_ip = {
|
||||
.chip_select_port = SPI_CS_PORT,
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
/***************************************************************************//**
|
||||
* @file parameters.h
|
||||
* @brief Definition of STM32 platform data used by adf4382 project.
|
||||
* @author CHegbeli (ciprian.hegbeli@analog.com))
|
||||
********************************************************************************
|
||||
* Copyright 2023(c) Analog Devices, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
#ifndef __PARAMETERS_H__
|
||||
#define __PARAMETERS_H__
|
||||
|
||||
#include "stm32_irq.h"
|
||||
#include "stm32_spi.h"
|
||||
#include "stm32_uart.h"
|
||||
//#include "stm32_uart_stdio.h"
|
||||
|
||||
extern UART_HandleTypeDef huart2;
|
||||
|
||||
#ifdef IIO_SUPPORT
|
||||
#define INTC_DEVICE_ID 0
|
||||
#define IIO_APP_HUART (&huart2)
|
||||
#endif
|
||||
#define UART_IRQ_ID UART5_IRQn
|
||||
|
||||
#define UART_DEVICE_ID 2
|
||||
#define UART_BAUDRATE 115200
|
||||
#define UART_EXTRA &adf4382_uart_extra_ip
|
||||
#define UART_OPS &stm32_uart_ops
|
||||
|
||||
#define SPI_DEVICE_ID 1
|
||||
#define SPI_BAUDRATE 4000000
|
||||
#define SPI_CS 0
|
||||
#define SPI_CS_PORT 3
|
||||
#define SPI_OPS &stm32_spi_ops
|
||||
#define SPI_EXTRA &adf4382_spi_extra_ip
|
||||
|
||||
extern struct stm32_uart_init_param adf4382_uart_extra_ip;
|
||||
extern struct stm32_spi_init_param adf4382_spi_extra_ip;
|
||||
|
||||
#endif /* __PARAMETERS_H__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* si5351.h - Si5351 library for Arduino
|
||||
*
|
||||
* Copyright (C) 2015 - 2019 Jason Milldrum <milldrum@gmail.com>
|
||||
* Dana H. Myers <k6jq@comcast.net>
|
||||
*
|
||||
* Many defines derived from clk-si5351.h in the Linux kernel.
|
||||
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
|
||||
* Rabeeh Khoury <rabeeh@solid-run.com>
|
||||
*
|
||||
* do_div() macro derived from /include/asm-generic/div64.h in
|
||||
* the Linux kernel.
|
||||
* Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SI5351_H_
|
||||
#define SI5351_H_
|
||||
|
||||
#include "main.h"
|
||||
#include "stm32f7xx_hal.h"
|
||||
#include "stm32f7xx_hal_i2c.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* Define definitions */
|
||||
|
||||
#define SI5351_BUS_BASE_ADDR 0x60
|
||||
#define SI5351_XTAL_FREQ 25000000
|
||||
#define SI5351_PLL_FIXED 80000000000ULL
|
||||
#define SI5351_FREQ_MULT 100ULL
|
||||
#define SI5351_DEFAULT_CLK 1000000000ULL
|
||||
|
||||
#define SI5351_PLL_VCO_MIN 600000000
|
||||
#define SI5351_PLL_VCO_MAX 900000000
|
||||
#define SI5351_MULTISYNTH_MIN_FREQ 500000
|
||||
#define SI5351_MULTISYNTH_DIVBY4_FREQ 150000000
|
||||
#define SI5351_MULTISYNTH_MAX_FREQ 225000000
|
||||
#define SI5351_MULTISYNTH_SHARE_MAX 100000000
|
||||
#define SI5351_MULTISYNTH_SHARE_MIN 1024000
|
||||
#define SI5351_MULTISYNTH67_MAX_FREQ SI5351_MULTISYNTH_DIVBY4_FREQ
|
||||
#define SI5351_CLKOUT_MIN_FREQ 4000
|
||||
#define SI5351_CLKOUT_MAX_FREQ SI5351_MULTISYNTH_MAX_FREQ
|
||||
#define SI5351_CLKOUT67_MS_MIN SI5351_PLL_VCO_MIN / SI5351_MULTISYNTH67_A_MAX
|
||||
#define SI5351_CLKOUT67_MIN_FREQ SI5351_CLKOUT67_MS_MIN / 128
|
||||
#define SI5351_CLKOUT67_MAX_FREQ SI5351_MULTISYNTH67_MAX_FREQ
|
||||
|
||||
#define SI5351_PLL_A_MIN 15
|
||||
#define SI5351_PLL_A_MAX 90
|
||||
#define SI5351_PLL_B_MAX (SI5351_PLL_C_MAX-1)
|
||||
#define SI5351_PLL_C_MAX 1048575
|
||||
#define SI5351_MULTISYNTH_A_MIN 6
|
||||
#define SI5351_MULTISYNTH_A_MAX 1800
|
||||
#define SI5351_MULTISYNTH67_A_MAX 254
|
||||
#define SI5351_MULTISYNTH_B_MAX (SI5351_MULTISYNTH_C_MAX-1)
|
||||
#define SI5351_MULTISYNTH_C_MAX 1048575
|
||||
#define SI5351_MULTISYNTH_P1_MAX ((1<<18)-1)
|
||||
#define SI5351_MULTISYNTH_P2_MAX ((1<<20)-1)
|
||||
#define SI5351_MULTISYNTH_P3_MAX ((1<<20)-1)
|
||||
#define SI5351_VCXO_PULL_MIN 30
|
||||
#define SI5351_VCXO_PULL_MAX 240
|
||||
#define SI5351_VCXO_MARGIN 103
|
||||
|
||||
#define SI5351_DEVICE_STATUS 0
|
||||
#define SI5351_INTERRUPT_STATUS 1
|
||||
#define SI5351_INTERRUPT_MASK 2
|
||||
#define SI5351_STATUS_SYS_INIT (1<<7)
|
||||
#define SI5351_STATUS_LOL_B (1<<6)
|
||||
#define SI5351_STATUS_LOL_A (1<<5)
|
||||
#define SI5351_STATUS_LOS (1<<4)
|
||||
#define SI5351_OUTPUT_ENABLE_CTRL 3
|
||||
#define SI5351_OEB_PIN_ENABLE_CTRL 9
|
||||
#define SI5351_PLL_INPUT_SOURCE 15
|
||||
#define SI5351_CLKIN_DIV_MASK (3<<6)
|
||||
#define SI5351_CLKIN_DIV_1 (0<<6)
|
||||
#define SI5351_CLKIN_DIV_2 (1<<6)
|
||||
#define SI5351_CLKIN_DIV_4 (2<<6)
|
||||
#define SI5351_CLKIN_DIV_8 (3<<6)
|
||||
#define SI5351_PLLB_SOURCE (1<<3)
|
||||
#define SI5351_PLLA_SOURCE (1<<2)
|
||||
|
||||
#define SI5351_CLK0_CTRL 16
|
||||
#define SI5351_CLK1_CTRL 17
|
||||
#define SI5351_CLK2_CTRL 18
|
||||
#define SI5351_CLK3_CTRL 19
|
||||
#define SI5351_CLK4_CTRL 20
|
||||
#define SI5351_CLK5_CTRL 21
|
||||
#define SI5351_CLK6_CTRL 22
|
||||
#define SI5351_CLK7_CTRL 23
|
||||
#define SI5351_CLK_POWERDOWN (1<<7)
|
||||
#define SI5351_CLK_INTEGER_MODE (1<<6)
|
||||
#define SI5351_CLK_PLL_SELECT (1<<5)
|
||||
#define SI5351_CLK_INVERT (1<<4)
|
||||
#define SI5351_CLK_INPUT_MASK (3<<2)
|
||||
#define SI5351_CLK_INPUT_XTAL (0<<2)
|
||||
#define SI5351_CLK_INPUT_CLKIN (1<<2)
|
||||
#define SI5351_CLK_INPUT_MULTISYNTH_0_4 (2<<2)
|
||||
#define SI5351_CLK_INPUT_MULTISYNTH_N (3<<2)
|
||||
#define SI5351_CLK_DRIVE_STRENGTH_MASK (3<<0)
|
||||
#define SI5351_CLK_DRIVE_STRENGTH_2MA (0<<0)
|
||||
#define SI5351_CLK_DRIVE_STRENGTH_4MA (1<<0)
|
||||
#define SI5351_CLK_DRIVE_STRENGTH_6MA (2<<0)
|
||||
#define SI5351_CLK_DRIVE_STRENGTH_8MA (3<<0)
|
||||
|
||||
#define SI5351_CLK3_0_DISABLE_STATE 24
|
||||
#define SI5351_CLK7_4_DISABLE_STATE 25
|
||||
#define SI5351_CLK_DISABLE_STATE_MASK 3
|
||||
#define SI5351_CLK_DISABLE_STATE_LOW 0
|
||||
#define SI5351_CLK_DISABLE_STATE_HIGH 1
|
||||
#define SI5351_CLK_DISABLE_STATE_FLOAT 2
|
||||
#define SI5351_CLK_DISABLE_STATE_NEVER 3
|
||||
|
||||
#define SI5351_PARAMETERS_LENGTH 8
|
||||
#define SI5351_PLLA_PARAMETERS 26
|
||||
#define SI5351_PLLB_PARAMETERS 34
|
||||
#define SI5351_CLK0_PARAMETERS 42
|
||||
#define SI5351_CLK1_PARAMETERS 50
|
||||
#define SI5351_CLK2_PARAMETERS 58
|
||||
#define SI5351_CLK3_PARAMETERS 66
|
||||
#define SI5351_CLK4_PARAMETERS 74
|
||||
#define SI5351_CLK5_PARAMETERS 82
|
||||
#define SI5351_CLK6_PARAMETERS 90
|
||||
#define SI5351_CLK7_PARAMETERS 91
|
||||
#define SI5351_CLK6_7_OUTPUT_DIVIDER 92
|
||||
#define SI5351_OUTPUT_CLK_DIV_MASK (7 << 4)
|
||||
#define SI5351_OUTPUT_CLK6_DIV_MASK (7 << 0)
|
||||
#define SI5351_OUTPUT_CLK_DIV_SHIFT 4
|
||||
#define SI5351_OUTPUT_CLK_DIV6_SHIFT 0
|
||||
#define SI5351_OUTPUT_CLK_DIV_1 0
|
||||
#define SI5351_OUTPUT_CLK_DIV_2 1
|
||||
#define SI5351_OUTPUT_CLK_DIV_4 2
|
||||
#define SI5351_OUTPUT_CLK_DIV_8 3
|
||||
#define SI5351_OUTPUT_CLK_DIV_16 4
|
||||
#define SI5351_OUTPUT_CLK_DIV_32 5
|
||||
#define SI5351_OUTPUT_CLK_DIV_64 6
|
||||
#define SI5351_OUTPUT_CLK_DIV_128 7
|
||||
#define SI5351_OUTPUT_CLK_DIVBY4 (3<<2)
|
||||
|
||||
#define SI5351_SSC_PARAM0 149
|
||||
#define SI5351_SSC_PARAM1 150
|
||||
#define SI5351_SSC_PARAM2 151
|
||||
#define SI5351_SSC_PARAM3 152
|
||||
#define SI5351_SSC_PARAM4 153
|
||||
#define SI5351_SSC_PARAM5 154
|
||||
#define SI5351_SSC_PARAM6 155
|
||||
#define SI5351_SSC_PARAM7 156
|
||||
#define SI5351_SSC_PARAM8 157
|
||||
#define SI5351_SSC_PARAM9 158
|
||||
#define SI5351_SSC_PARAM10 159
|
||||
#define SI5351_SSC_PARAM11 160
|
||||
#define SI5351_SSC_PARAM12 161
|
||||
|
||||
#define SI5351_VXCO_PARAMETERS_LOW 162
|
||||
#define SI5351_VXCO_PARAMETERS_MID 163
|
||||
#define SI5351_VXCO_PARAMETERS_HIGH 164
|
||||
|
||||
#define SI5351_CLK0_PHASE_OFFSET 165
|
||||
#define SI5351_CLK1_PHASE_OFFSET 166
|
||||
#define SI5351_CLK2_PHASE_OFFSET 167
|
||||
#define SI5351_CLK3_PHASE_OFFSET 168
|
||||
#define SI5351_CLK4_PHASE_OFFSET 169
|
||||
#define SI5351_CLK5_PHASE_OFFSET 170
|
||||
|
||||
#define SI5351_PLL_RESET 177
|
||||
#define SI5351_PLL_RESET_B (1<<7)
|
||||
#define SI5351_PLL_RESET_A (1<<5)
|
||||
|
||||
#define SI5351_CRYSTAL_LOAD 183
|
||||
#define SI5351_CRYSTAL_LOAD_MASK (3<<6)
|
||||
#define SI5351_CRYSTAL_LOAD_0PF (0<<6)
|
||||
#define SI5351_CRYSTAL_LOAD_6PF (1<<6)
|
||||
#define SI5351_CRYSTAL_LOAD_8PF (2<<6)
|
||||
#define SI5351_CRYSTAL_LOAD_10PF (3<<6)
|
||||
|
||||
#define SI5351_FANOUT_ENABLE 187
|
||||
#define SI5351_CLKIN_ENABLE (1<<7)
|
||||
#define SI5351_XTAL_ENABLE (1<<6)
|
||||
#define SI5351_MULTISYNTH_ENABLE (1<<4)
|
||||
|
||||
|
||||
/* Macro definitions */
|
||||
|
||||
//#define RFRAC_DENOM ((1L << 20) - 1)
|
||||
#define RFRAC_DENOM 1000000ULL
|
||||
|
||||
/*
|
||||
* Based on former asm-ppc/div64.h and asm-m68knommu/div64.h
|
||||
*
|
||||
* The semantics of do_div() are:
|
||||
*
|
||||
* uint32_t do_div(uint64_t *n, uint32_t base)
|
||||
* {
|
||||
* uint32_t remainder = *n % base;
|
||||
* *n = *n / base;
|
||||
* return remainder;
|
||||
* }
|
||||
*
|
||||
* NOTE: macro parameter n is evaluated multiple times,
|
||||
* beware of side effects!
|
||||
*/
|
||||
|
||||
# define do_div(n,base) ({ \
|
||||
uint64_t __base = (base); \
|
||||
uint64_t __rem; \
|
||||
__rem = ((uint64_t)(n)) % __base; \
|
||||
(n) = ((uint64_t)(n)) / __base; \
|
||||
__rem; \
|
||||
})
|
||||
|
||||
/* Enum definitions */
|
||||
|
||||
/*
|
||||
* enum si5351_variant - SiLabs Si5351 chip variant
|
||||
* @SI5351_VARIANT_A: Si5351A (8 output clocks, XTAL input)
|
||||
* @SI5351_VARIANT_A3: Si5351A MSOP10 (3 output clocks, XTAL input)
|
||||
* @SI5351_VARIANT_B: Si5351B (8 output clocks, XTAL/VXCO input)
|
||||
* @SI5351_VARIANT_C: Si5351C (8 output clocks, XTAL/CLKIN input)
|
||||
*/
|
||||
/*
|
||||
enum si5351_variant {
|
||||
SI5351_VARIANT_A = 1,
|
||||
SI5351_VARIANT_A3 = 2,
|
||||
SI5351_VARIANT_B = 3,
|
||||
SI5351_VARIANT_C = 4,
|
||||
};
|
||||
*/
|
||||
|
||||
enum si5351_clock {SI5351_CLK0, SI5351_CLK1, SI5351_CLK2, SI5351_CLK3,
|
||||
SI5351_CLK4, SI5351_CLK5, SI5351_CLK6, SI5351_CLK7};
|
||||
|
||||
enum si5351_pll {SI5351_PLLA, SI5351_PLLB};
|
||||
|
||||
enum si5351_drive {SI5351_DRIVE_2MA, SI5351_DRIVE_4MA, SI5351_DRIVE_6MA, SI5351_DRIVE_8MA};
|
||||
|
||||
enum si5351_clock_source {SI5351_CLK_SRC_XTAL, SI5351_CLK_SRC_CLKIN, SI5351_CLK_SRC_MS0, SI5351_CLK_SRC_MS};
|
||||
|
||||
enum si5351_clock_disable {SI5351_CLK_DISABLE_LOW, SI5351_CLK_DISABLE_HIGH, SI5351_CLK_DISABLE_HI_Z, SI5351_CLK_DISABLE_NEVER};
|
||||
|
||||
enum si5351_clock_fanout {SI5351_FANOUT_CLKIN, SI5351_FANOUT_XO, SI5351_FANOUT_MS};
|
||||
|
||||
enum si5351_pll_input {SI5351_PLL_INPUT_XO, SI5351_PLL_INPUT_CLKIN};
|
||||
|
||||
/* Struct definitions */
|
||||
|
||||
struct Si5351RegSet
|
||||
{
|
||||
uint32_t p1;
|
||||
uint32_t p2;
|
||||
uint32_t p3;
|
||||
};
|
||||
|
||||
struct Si5351Status
|
||||
{
|
||||
uint8_t SYS_INIT;
|
||||
uint8_t LOL_B;
|
||||
uint8_t LOL_A;
|
||||
uint8_t LOS;
|
||||
uint8_t REVID;
|
||||
};
|
||||
|
||||
struct Si5351IntStatus
|
||||
{
|
||||
uint8_t SYS_INIT_STKY;
|
||||
uint8_t LOL_B_STKY;
|
||||
uint8_t LOL_A_STKY;
|
||||
uint8_t LOS_STKY;
|
||||
};
|
||||
|
||||
class Si5351
|
||||
{
|
||||
public:
|
||||
Si5351(uint8_t i2c_addr = SI5351_BUS_BASE_ADDR);
|
||||
bool init(uint8_t, uint32_t, int32_t);
|
||||
void reset(void);
|
||||
uint8_t set_freq(uint64_t, enum si5351_clock);
|
||||
uint8_t set_freq_manual(uint64_t, uint64_t, enum si5351_clock);
|
||||
void set_pll(uint64_t, enum si5351_pll);
|
||||
void set_ms(enum si5351_clock, struct Si5351RegSet, uint8_t, uint8_t, uint8_t);
|
||||
void output_enable(enum si5351_clock, uint8_t);
|
||||
void drive_strength(enum si5351_clock, enum si5351_drive);
|
||||
void update_status(void);
|
||||
void set_correction(int32_t, enum si5351_pll_input);
|
||||
void set_phase(enum si5351_clock, uint8_t);
|
||||
int32_t get_correction(enum si5351_pll_input);
|
||||
void pll_reset(enum si5351_pll);
|
||||
void set_ms_source(enum si5351_clock, enum si5351_pll);
|
||||
void set_int(enum si5351_clock, uint8_t);
|
||||
void set_clock_pwr(enum si5351_clock, uint8_t);
|
||||
void set_clock_invert(enum si5351_clock, uint8_t);
|
||||
void set_clock_source(enum si5351_clock, enum si5351_clock_source);
|
||||
void set_clock_disable(enum si5351_clock, enum si5351_clock_disable);
|
||||
void set_clock_fanout(enum si5351_clock_fanout, uint8_t);
|
||||
void set_pll_input(enum si5351_pll, enum si5351_pll_input);
|
||||
void set_vcxo(uint64_t, uint8_t);
|
||||
void set_ref_freq(uint32_t, enum si5351_pll_input);
|
||||
uint8_t si5351_write_bulk(uint8_t, uint8_t, uint8_t *);
|
||||
uint8_t si5351_write(uint8_t, uint8_t);
|
||||
uint8_t si5351_read(uint8_t);
|
||||
struct Si5351Status dev_status = {.SYS_INIT = 0, .LOL_B = 0, .LOL_A = 0,
|
||||
.LOS = 0, .REVID = 0};
|
||||
struct Si5351IntStatus dev_int_status = {.SYS_INIT_STKY = 0, .LOL_B_STKY = 0,
|
||||
.LOL_A_STKY = 0, .LOS_STKY = 0};
|
||||
enum si5351_pll pll_assignment[8];
|
||||
uint64_t clk_freq[8];
|
||||
uint64_t plla_freq;
|
||||
uint64_t pllb_freq;
|
||||
enum si5351_pll_input plla_ref_osc;
|
||||
enum si5351_pll_input pllb_ref_osc;
|
||||
uint32_t xtal_freq[2];
|
||||
private:
|
||||
uint64_t pll_calc(enum si5351_pll, uint64_t, struct Si5351RegSet *, int32_t, uint8_t);
|
||||
uint64_t multisynth_calc(uint64_t, uint64_t, struct Si5351RegSet *);
|
||||
uint64_t multisynth67_calc(uint64_t, uint64_t, struct Si5351RegSet *);
|
||||
void update_sys_status(struct Si5351Status *);
|
||||
void update_int_status(struct Si5351IntStatus *);
|
||||
void ms_div(enum si5351_clock, uint8_t, uint8_t);
|
||||
uint8_t select_r_div(uint64_t *);
|
||||
uint8_t select_r_div_ms67(uint64_t *);
|
||||
int32_t ref_correction[2];
|
||||
uint8_t clkin_div;
|
||||
uint8_t i2c_bus_addr;
|
||||
bool clk_first_set[8];
|
||||
};
|
||||
|
||||
#endif /* SI5351_H_ */
|
||||
Reference in New Issue
Block a user