this repo has no description

Vendor sw and scripts into main repo

Removes sw and sw/scripts as nested submodules; all source files are now
tracked directly in ragtag. Based on Digilent/Zybo-Z7-SW @ 06f2b4d and
digilent-vitis-scripts @ branch new_vitis/dev2024.1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

oscillatory.net 354f514f a5f11f2e

verified
+4745 -3
-3
.gitmodules
··· 1 1 [submodule "hw"] 2 2 path = hw 3 3 url = https://github.com/Digilent/Zybo-Z7-HW.git 4 - [submodule "sw"] 5 - path = sw 6 - url = https://github.com/Digilent/Zybo-Z7-SW.git 7 4 [submodule "os"] 8 5 path = os 9 6 url = https://github.com/Digilent/Zybo-Z7-OS.git
+14
sw/.gitignore
··· 1 + # ignore everything in workspace sub-dir 2 + 3 + /ws/* 4 + 5 + # except the cleanup scripts 6 + 7 + !/ws/cleanup.cmd 8 + !/ws/cleanup.sh 9 + 10 + # ignore Packages/ and wsdata/ created by Vitis 11 + 12 + /Packages 13 + /.wsdata 14 + dfx_runtime.txt
+25
sw/README.md
··· 1 + 2 + # Zybo Z7 Software Repository 3 + 4 + ## Zybo Z7-20 Pcam 5C Demo 5 + 6 + For more information on the Zybo Z7, see its [Resource Center](https://reference.digilentinc.com/reference/programmable-logic/zybo-z7/start) on the Digilent Wiki. 7 + 8 + For more information on the Zybo Z7-20 Pcam 5C Demo, including setup instructions, visit its [Demo Page](https://reference.digilentinc.com/reference/programmable-logic/zybo-z7/demos/pcam-5c) on the Digilent Wiki. 9 + 10 + For instructions on how to use this repository with git, and for additional documentation on the submodule and branch structures used, please visit [Digilent FPGA Demo Git Repositories](https://reference.digilentinc.com/reference/programmable-logic/documents/git) on the Digilent Wiki. Note that use of git is not required to use this demo. Digilent recommends the use of project releases, for which instructions can be found in the demo wiki page, linked above. 11 + 12 + Note: If using git, as this demo requires sources for tools other than Vitis, which are provided in other repos, it is recommended to get these sources through the corresponding branch of the Zybo-Z7 repository, which uses submodules to bring in sources for all tools used by this demo. This is described in the Digilent FPGA Demo Git Repositories page, linked above. 13 + 14 + ## New Vitis workflow 15 + 16 + This functionality can be reproduced from Vitis IDE by launching the terminal from 17 + Terminal -> New Terminal which uses the default command line executable from the OS, 18 + or simply manually invoke the native terminal. If this is the choosen method, then it will be necessary to give absolute path to the `checkout.py` 19 + or `checkin.py` file, not relative, or to change current working directory to the wanted sw submodule branch. 20 + 21 + > `vitis -s <path-to-scripts-repo>checkout.py` 22 + 23 + or 24 + 25 + > `vitis -s <path-to-scripts-repo>checkin.py`
+3
sw/scripts/.gitignore
··· 1 + # ignore cache folder created by Python 2 + 3 + /__pycache__/*
+21
sw/scripts/LICENSE
··· 1 + MIT License 2 + 3 + Copyright (c) 2025 Digilent 4 + 5 + Permission is hereby granted, free of charge, to any person obtaining a copy 6 + of this software and associated documentation files (the "Software"), to deal 7 + in the Software without restriction, including without limitation the rights 8 + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 + copies of the Software, and to permit persons to whom the Software is 10 + furnished to do so, subject to the following conditions: 11 + 12 + The above copyright notice and this permission notice shall be included in all 13 + copies or substantial portions of the Software. 14 + 15 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 + SOFTWARE.
+104
sw/scripts/README.md
··· 1 + 2 + # digilent-vitis-scripts 3 + 4 + This is a development branch for Vitis 2024.1, 5 + it contains for now solutions for check in/out workflow. 6 + 7 + **Special Notes:** 8 + *Vitis creates a `.lock` file which after the IDE is closed or other* 9 + *Vitis TCP/IP server is stopped, it will have its file descriptor still* 10 + *hooked up to the previous process, so only after a few seconds should* 11 + *one of the files be run.* 12 + 13 + ---- 14 + 15 + ## Quick Checkout Guide 16 + 17 + Some Digilent Github repositories also require that you check out a specific demo branch. 18 + Whenever checking out a demo branch, submodules should be updated and initialized: 19 + 20 + `git submodule update --init [--recursive]` 21 + 22 + When launching Vitis, whether through Vivado's *Tools* menu, or on its own, 23 + the Vitis workspace should be set to the repository's sw -> ws folder. 24 + 25 + The scripts present in this repository can be run through the use of the 26 + Vitis Console 202x.y, for example 2024.1, which comes along with Vitis. 27 + Upon launch, Vitis Console's current working directory is set to the 28 + Vitis install directory: Xilinx -> Vitis -> 202x.y -> bin. 29 + To recreate the workspace, enter the following command into the Vitis Console: 30 + 31 + `<path-to-scripts-repo>checkout.py` 32 + 33 + This process will populate the workspace with projects containing sources 34 + from the parent repository's `src` folder, configure those projects, and fully build them. 35 + This may take several minutes to fully complete. When the script is finished running, 36 + the `Vitis [idx]:` prompt wil reappear in the command line, where `idx - 1` is the number of 37 + inserted commands. From this point, the demo can be programmed onto a board, 38 + sources can be viewed, and modified, as desired. 39 + 40 + The above functionality can be reproduced from Vitis IDE launching the terminal from 41 + Terminal -> New Terminal which uses the default command line executable from the OS. If 42 + this is the choosen method, then it will be necessary to give absolute path to the `checkout.py` 43 + file, not relative, or to change current working directory to the branch's sw submodule. 44 + 45 + `vitis -s <path-to-scripts-repo>checkout.py` 46 + 47 + **Note:** 48 + *The current working directory is irrelevant to the functionality of the scripts in this submodule.* 49 + 50 + ---- 51 + 52 + ## Quick Checkin Guide 53 + 54 + **Important:** *The checkin.py can be used multiple times, it will overwrite the existent* 55 + *files and if some new ones appear into an application they are going to be copied too.* 56 + 57 + *Application source files (cmake and linker scripts) are soft-linked into the* 58 + *workspace upon checkout, so existing files do not need to be manually copied back,* 59 + *but the checkin.py saves them because can hold modifications, Vitis generates them* 60 + *with respect to the application template and hardware platform.* 61 + 62 + This section assumes that you have already created a Vitis workspace containing 63 + one or more application projects. 64 + 65 + The checkin script has only been tested with standalone application projects at time of writing. 66 + 67 + To add this repository to a parent repository as a submodule, first open a terminal 68 + with access to `git`. If your parent repository does not yet have a `sw` subdirectory (or submodule), 69 + create one and `cd` into it. Adding the `scripts` path argument to the command is recommended 70 + in order to keep file paths short. 71 + 72 + `git submodule add https://github.com/Digilent/digilent-vitis-scripts scripts` 73 + 74 + `git checkout new_vitis/2024.1` 75 + 76 + The scripts presented in this repository can be run through the use of the 77 + Vitis Console 202x.y, for example 2024.1, which comes along with Vitis. 78 + Upon launch, Vitis Console's current working directory is set to the 79 + Vitis install directory: Xilinx -> Vitis -> 202x.y -> bin. 80 + To backup the workspace, enter the following command into the Vitis Console: 81 + 82 + `<path-to-scripts-repo>checkin.py` 83 + 84 + The above functionality can be reproduced from Vitis IDE launching the terminal from 85 + Terminal -> New Terminal which uses the default command line executable from the OS. If 86 + this is the choosen method, then it will be necessary to give absolute path to the `checkin.py` 87 + file, not relative, or to change current working directory to the wanted sw submodule branch. 88 + 89 + `vitis -s <path-to-scripts-repo>checkin.py` 90 + 91 + This script needs to have `src` directory in the same folder as the scripts submodule, populating it as below: 92 + 93 + * One folder per hardware platform 94 + * The XSA file describing the hardware specification that the software targets, exported from Vivado. 95 + * One folder per application project, containing the following: 96 + * A comp-settings.json file with user settings and relative path to XSA file used by a project. 97 + * A src directory with source files and cmake, linker scripts. 98 + 99 + Note that the name of each folder is used in `checkout` to determine the name of the app/platform/domain. 100 + 101 + The checkin/out scripts will handle all the neccessary tasks to ensure a smooth workflow 102 + for development of `projects`. 103 + 104 + ----
+749
sw/scripts/checkin.py
··· 1 + 2 + """ 3 + Company: Digilent RO 4 + Engineer: bs 5 + Usage: for vitis projects 6 + 7 + @Description 8 + This checkin.py has the same behavior 9 + as the previous checkin.tcl. It preserves 10 + workspace configuration & source files. 11 + 12 + @Insights 13 + Vitis v2024.1 has Python v3.8.3. 14 + """ 15 + from os import (chdir, getcwd, listdir, 16 + path, sep, makedirs, mkdir, 17 + access, F_OK, SEEK_END) 18 + from vitis import (_build, _server) 19 + from pathlib import Path 20 + from shutil import copy 21 + from json import (JSONEncoder, JSONDecoder) 22 + from re import (compile, RegexFlag) 23 + from misc import LOG 24 + 25 + class UtilityWS: 26 + """ 27 + @Description 28 + Extract data / Generate data from 29 + specific workspace files like *.spfm. 30 + 31 + @Insights 32 + comp-settings.json structure (example): 33 + { 34 + CFLAGS : ["", "", "", ...] 35 + TEMPLATE : ["..."], 36 + LFLAGS : ["", "", "", ...], 37 + PREV_BUILDSTATUS : ["Valid"], 38 + PART : ["<part-number>"] 39 + } 40 + """ 41 + srvCl = None 42 + EMPTY_BUFFER = 0 43 + FAILURE = -1 44 + SUCCESS = 0 45 + COMP_TYPES = ["UNKNOWN", "AI_ENGINE", "PL_KERNEL", "HOST", 46 + "HLS", "USER_MANAGED_KERNEL", "PLATFORM" 47 + ] 48 + # configuration -> {} -> "componentType", "hostToolchainConfigurations" 49 + COMP_MISC = ["name", "type", "domain", "cpuInstance", 50 + "cpuType", "os", "configuration", "domainRealName", 51 + "applicationFlow" 52 + ] 53 + IS_DIRS = False 54 + 55 + def __init__(self): 56 + """ 57 + @Description 58 + This file has its location directory as the starting point, 59 + then `src`, `ws` need to exist before any checkin flow to 60 + happen. If these have not been created by default on a branch, 61 + all the checkin flow would be bypassed, then logging some Warning 62 + Message into default <stream-buff>, default is cmd-line. 63 + 64 + Other files are stored in self._lfConf that have valuable data for 65 + platform/project. Through vitis-py resources or custom logic can be 66 + extracted, this depends on what other features checkin flow needs 67 + to have. Class dependent variables are set, like COMP_TYPES, srvCl, 68 + these are `utilities` for vitis-workspaces. 69 + """ 70 + # Always have a reference wd. 71 + self._wDir = path.dirname(path.realpath(__file__)) 72 + # os.sep ~ platform dependent; 73 + self._pSubSw = self._wDir[:self._wDir.rfind(sep)] 74 + chdir(self._pSubSw) 75 + # Can be changed to other dir (new or existent); 76 + self._srcDir = "src" 77 + # App or prj ? 78 + # Set path for win/lnx "\\" or "/"; Use py-stdlib 79 + # functions to avoid manually use/change these OS differences. 80 + self._appDir = "ws" 81 + # '*' -> Substitute with platform name (example only), <vitis-comp>.json; 82 + self._lfConf = ["*.xpfm", "*.json", "*.cmake", 83 + "*.yaml", "qemu_args.txt", "*.spfm", 84 + "*.cfg" 85 + ] 86 + self.wsJsonConf = "comp-settings.json" 87 + self.dConfWs = {} 88 + self._dPltAppCorr = {} 89 + self.enJsonObjFile = JSONEncoder(indent="\t", separators=(",", " : ")) 90 + # Check for src and ws dirs. 91 + lcWsDir = path.join(self._pSubSw, self._appDir) 92 + if path.isdir(self._srcDir) and path.isdir(self._appDir): 93 + if UtilityWS.srvCl is None: 94 + try: 95 + LOG(msg="Local server, starting Vitis server...") 96 + # Init server with pre-defined args. 97 + UtilityWS.srvCl = _server.Server( 98 + port=None, 99 + host="localhost", 100 + workspace=lcWsDir 101 + ) 102 + UtilityWS.IS_DIRS = True 103 + except Exception as err: 104 + LOG(msg=f"Error Local server: {err.__class__} {err.__context__}") 105 + 106 + def encJSON_Ws(self, 107 + bdRes : list, 108 + locations : list 109 + ) -> int: 110 + """ 111 + @Description 112 + Prepare build/ws metadata to be saved into a json file for 113 + each existent application. Get <app-dirname> with rfind + 114 + sep tweaks to create json file under it after data is 115 + prepared with self.prepDataStruct(). Module json has encoder + 116 + decoder classes to get/set json data structure, this format has 117 + been choosen because vitis generates similar files. 118 + 119 + @Parameters 120 + bdRes: List with build chace representative structure. 121 + location: Where the self.wsJsonConf will be saved. 122 + """ 123 + idx = 0 124 + for location in locations: 125 + # Save apps/platforms into a json dt at checkin, with 126 + # flags, template !!, processor, target, ... etc. 127 + dirApp = location[location.rfind(sep) + 1:] 128 + sPrevWd = getcwd() 129 + chdir(dirApp) 130 + iRet = self.prepDataStruct(bdRes[idx]) 131 + # Add relative path to json settings. 132 + self.dConfWs[dirApp] = self._dPltAppCorr[dirApp] 133 + if iRet != UtilityWS.FAILURE: 134 + sFConfWs = self.enJsonObjFile.encode(self.dConfWs) 135 + with open(self.wsJsonConf, "w+", encoding="utf-8") as fd: 136 + fd.write("\n" + sFConfWs + "\n") 137 + LOG(f"File sw{sep}src{sep}{dirApp}{sep}{self.wsJsonConf} has been created!") 138 + else: 139 + LOG("Data structure from Vitis modules has NOT been parsed correctly!") 140 + return UtilityWS.FAILURE 141 + chdir(sPrevWd) 142 + if idx < len(bdRes): 143 + idx = idx + 1 144 + del self.dConfWs[dirApp] 145 + return UtilityWS.SUCCESS 146 + 147 + def prepDataStruct(self, 148 + obj 149 + ) -> int: 150 + """ 151 + @Description 152 + Only with a debugger it's easy to profile/study the nested data 153 + structure the obj parameter will hold. The below logic is depenent on 154 + obj, obj.settings is a subclass of type(obj), item.(key or value) are 155 + string, list respectively. len() or item.value.__len__() function can be 156 + used, item.value.__getitem__(idx) is class dependent, but can have an 157 + equivalent. Some item.value are of dim=0, so empty list is stored. 158 + 159 + @Parameters 160 + obj: The type of this item is dependent on vitis-py resources, 161 + it consists of a nested data structure. 162 + """ 163 + # Extract from a protobuff class metadata. 164 + for item in obj.settings: 165 + if len(item.value) != UtilityWS.EMPTY_BUFFER: 166 + # Every value-obj has just one element in its list ? ... some maybe not. 167 + valLoc = item.value.__getitem__(0) 168 + self.dConfWs[item.key] = valLoc if type(valLoc) is list else [valLoc] 169 + else: 170 + self.dConfWs[item.key] = [] 171 + return UtilityWS.SUCCESS 172 + 173 + @property 174 + def dPltAppCorr(self) -> dict: 175 + """ Get reference for self._dPltAppCorr """ 176 + return self._dPltAppCorr 177 + 178 + @property 179 + def appDir(self) -> str: 180 + """ Get reference for self._appDir """ 181 + return self._appDir 182 + 183 + @property 184 + def lfConf(self) -> list: 185 + """ Get reference for self._lfConf """ 186 + return self._lfConf 187 + 188 + @property 189 + def wDir(self) -> str: 190 + """ Get reference for self._wDir """ 191 + return self._wDir 192 + 193 + @property 194 + def srcDir(self) -> str: 195 + """ Get reference for self._srcDir """ 196 + return self._srcDir 197 + 198 + @property 199 + def pSubSw(self) -> str: 200 + """ Get reference for self._pSubSw """ 201 + return self._pSubSw 202 + 203 + class ConfigWS: 204 + """ 205 + @Description 206 + Extract metadata with vitis tools, 207 + process them here and use them where it's needed. 208 + """ 209 + def __init__(self, 210 + lApps : list = None 211 + ): 212 + """ 213 + @Description 214 + This unit is mainly used to interact with vitis-py resources to 215 + extract different data from auto generated files. In some cases, 216 + it's easier to implement an indepentend logic for a certain feature. 217 + 218 + @Insights 219 + Apps are more important to have them stored. 220 + Not all vitis-py resources are easily to be used. 221 + From vitis :: component.py: get_app_config, set_sysroot, get_config_info, 222 + get_ld_script, ... . 223 + Check out more resources from vitis-tools to encode medata into config_ws.json. 224 + """ 225 + self._utilCfgWs = UtilityWS() 226 + self.bdComp = _build.Build(server=UtilityWS.srvCl) 227 + # Store all configs from apps. 228 + self._bdRes = [] 229 + # Py makes here a reference automatically, _ref<...> just for intuitive distinction. 230 + self._refLApps = [] 231 + if UtilityWS.IS_DIRS and lApps is not None: 232 + self.setApps(lApps) 233 + 234 + def setApps(self, lApps : list) -> None: 235 + self._refLApps = lApps 236 + for item in lApps: 237 + self._bdRes.append( 238 + self.bdComp.getAppConfig( 239 + component_location=item 240 + ) 241 + ) 242 + 243 + @property 244 + def dPltAppCorr(self) -> dict: 245 + """ Get reference for self._utilSFWs.dPltAppCorr """ 246 + return self._utilCfgWs.dPltAppCorr 247 + 248 + @property 249 + def bdRes(self) -> list: 250 + """ Get reference for self._bdRes """ 251 + return self._bdRes 252 + 253 + @property 254 + def refLApps(self) -> list: 255 + """ Get reference for self._refLApps """ 256 + return self._refLApps 257 + 258 + @property 259 + def utilCfgWs(self): 260 + """ Get reference for self._utilCfgWs """ 261 + return self._utilCfgWs 262 + 263 + class SrcFilesWS: 264 + """ 265 + @Description 266 + Copy apps source files into local dir 'src' 267 + that is present in all projects branches. 268 + """ 269 + # Consts 270 + BUILD_FILE_IDX = 0 271 + COMP_FILE_IDX = 1 272 + # Predef vectors - some files need to have a standard name. 273 + # Note :: First and last item are always excluded. 274 + lsConfCpy = ["CMakeLists.txt", "vitis-comp.json", "*.cmake", 275 + "*.ld", "Makefile", ".gitignore" 276 + ] 277 + lsSrcCpy = ["*.h", "*.hpp", "*.c", 278 + "*.cpp", "*.cc", "*.S", 279 + "*.scat", "*.mk", "*.C", 280 + "*.cxx", "*.c++", "*.s" 281 + ] 282 + HOFF_HDL = "*.xsa" 283 + FAILURE = -1 284 + SUCCESS = 0 285 + APP_SRCCODE = "src" 286 + EXCLUDE_BSYSF_IDX = 1 287 + 288 + def __init__(self): 289 + """ 290 + @Description 291 + Init base vectors that will hold paths to build, handoff, platform-dir, 292 + and app-src paths, these are important for preserving workspace for 293 + Vitis >= 2023.2. Getter are provided to take references to below lists, 294 + making them usable in other contexts. 295 + """ 296 + self.utilSFWs = UtilityWS() 297 + # There are other extensions, check for a pattern if one is not in the below list. 298 + # Path(s) of build-system script; 299 + self._lsBldFl = [] 300 + # Path(s) of xsa files; 301 + self._lsArchFl = [] 302 + # Dir(s) for platforms; 303 + self._lsArchPltDir = [] 304 + # Buffer to store Path(s) of src files; 305 + self._lsTempSrcFl = [] 306 + 307 + @property 308 + def dPltAppCorr(self) -> dict: 309 + """ Get reference for self.utilSFWs.dPltAppCorr """ 310 + return self.utilSFWs.dPltAppCorr 311 + 312 + @property 313 + def appDir(self) -> str: 314 + """ Get reference for self.utilSFWs.appDir """ 315 + return self.utilSFWs.appDir 316 + 317 + @property 318 + def wDir(self) -> str: 319 + """ Get reference for self.utilSFWs.wDir """ 320 + return self.utilSFWs.wDir 321 + 322 + @property 323 + def pSubSw(self) -> str: 324 + """ Get reference for self.utilSFWs.pSubSw """ 325 + return self.utilSFWs.pSubSw 326 + 327 + def collectCpyFiles(self, 328 + lApps : list 329 + ) -> int: 330 + """ 331 + @Description 332 + Only in this function (+ self.cpySrcFiles, or others if the code is extended) 333 + are files copied through copy or copy2 stdlib functions. Keep things 334 + well structured to not make mistakes. Before copying files, some conditions 335 + need to be respected otherwise stdlib functions may raise exceptions. 336 + 337 + path.join function is mainly used to create paths that are system 338 + dependent, in some cases os.sep (separator) is used. Nr of platforms 339 + should be lower than that of applications of equal, but this case is treated 340 + anyway. Different tweaks with rfind and itemIdx are implemented to extract from 341 + lApps a certain path, in this function it is <app-dirname>. 342 + 343 + self.lsBldFl and self.lsArchFl contain paths to build, xsa files, these are copied 344 + directly within this function, but others are in self.cpySrcFiles to not have 345 + ultimately a large function. In case this function has copied everything we need 346 + it returns 0, otherwise -1 if some error occured. The error must not exit the program 347 + randomly, but close it without any undefined behavor. 348 + 349 + @Parameters 350 + lApps: ref to matrix with paths of files to be copied. 351 + """ 352 + if lApps is None or len(lApps) == UtilityWS.EMPTY_BUFFER: 353 + return SrcFilesWS.FAILURE 354 + pTemp = path.join(self.utilSFWs.pSubSw, SrcFilesWS.APP_SRCCODE) 355 + dimLsBldFl = len(self.lsBldFl) 356 + dimLsArchFl = len(self.lsArchFl) 357 + # These lists should have been populated by now. 358 + if (dimLsBldFl == UtilityWS.EMPTY_BUFFER or 359 + dimLsArchFl == UtilityWS.EMPTY_BUFFER 360 + ): 361 + return SrcFilesWS.FAILURE 362 + elif path.isdir(pTemp) is True: 363 + # Copy files into 'src' dir. 364 + chdir(pTemp) 365 + # Find the largest vector. 366 + bigLs = dimLsBldFl if dimLsBldFl > dimLsArchFl else dimLsArchFl 367 + # Nr of platforms <= Nr of apps; 368 + for itemIdx in range(0, bigLs): 369 + if itemIdx < dimLsBldFl: 370 + strTempLoc = lApps[itemIdx][lApps[itemIdx].rfind(sep) + 1:] 371 + else: 372 + continue 373 + dTempLoc = path.join(strTempLoc, SrcFilesWS.APP_SRCCODE) 374 + # In py <= 3.8, certain modes for mkdir does not exist, so default one is used. 375 + if path.isdir(dTempLoc) is not True: 376 + makedirs(dTempLoc) 377 + if itemIdx < dimLsArchFl: 378 + mkdir(self.lsArchPltDir[itemIdx]) 379 + # Should we use copy2 to preserve metadata instead of copy ? 380 + copy(self.lsBldFl[itemIdx], dTempLoc) 381 + if itemIdx < dimLsArchFl: 382 + copy(self.lsArchFl[itemIdx], self.lsArchPltDir[itemIdx]) 383 + # tuple(<app-dirname-src>, <app-dirname>) 384 + iRet = self.cpySrcFiles(itemIdx, lApps, (dTempLoc, strTempLoc)) 385 + # Handoff (xsa) and build script files have been copied, src files too. 386 + LOG(f"Matching directories have been created in sw{sep}src") 387 + return SrcFilesWS.SUCCESS 388 + else: 389 + return SrcFilesWS.FAILURE 390 + 391 + def cpySrcFiles(self, 392 + appIdx : int, 393 + lApps : list, 394 + locDuo : tuple 395 + ) -> int: 396 + """ 397 + @Description 398 + Current function is called in self.collectCpyFiles to divide 399 + some steps and limit function code. In this one, files corresponding 400 + to an application type are copied to 'src-<app-dirname>', <app-dirname> 401 + and <default-src> come in tuple form `locDuo`, because there can be some 402 + files which should be put in <app-dirname>, not <src>. 403 + 404 + srcDirLoc and LocFMisc are equal only when a file needs to be copied 405 + into <app-dirname>, like `.gitignore`, but these type of files are excluded 406 + by default (check out gatherAppOtherConf from Workspace which has repflOpt 407 + on False implicitly). Each file type is stored into a list, which will be 408 + iterated over with below 2x for structure. 409 + 410 + rfind + slices (idxLeft:idxRight) are used to get directories that need 411 + to be created for header files into <app-dirname-src>, if not they are 412 + overwritten anyway. In case of directories, if they have been already 413 + created, then calling `mkdir` or `makedirs` like functions are avoided. 414 + 415 + @Parameters 416 + appIdx: integer for App(s) files. 417 + lApps: matrix with paths of files to be copied. 418 + locDuo: tuple with <app-dirname-src> on left, <app-dirname> on right ~ pair like. 419 + """ 420 + # item ~ list 421 + # e.g. appIdx=0 is for App1. 422 + loc, locFMisc = locDuo 423 + for item in self._lsTempSrcFl[appIdx]: 424 + for subItem in item: 425 + # Take all files from each sublist and copy them, 426 + # suppose only one dir is between <app-dir-src> and a header file. 427 + lastMarkerPos = subItem.rfind(sep) 428 + miscFileName = subItem[lastMarkerPos + 1:] 429 + trimSubItem = subItem[:lastMarkerPos] 430 + prevLastMarkerPos = trimSubItem.rfind(sep) + 1 431 + srcDirLoc = subItem[prevLastMarkerPos:lastMarkerPos] 432 + if srcDirLoc != SrcFilesWS.APP_SRCCODE and srcDirLoc != locFMisc: 433 + nLoc = path.join(loc, srcDirLoc) 434 + if path.isdir(nLoc) is not True: 435 + mkdir(nLoc) 436 + copy(subItem, nLoc) 437 + continue 438 + # Prefix - other misc files can exist ... tp(".","") 439 + if miscFileName.startswith("."): 440 + copy(subItem, locFMisc) 441 + else: 442 + copy(subItem, loc) 443 + return SrcFilesWS.SUCCESS 444 + 445 + @property 446 + def lsTempSrcFl(self) -> list: 447 + """ Get reference for self._lsTempSrcFl """ 448 + return self._lsTempSrcFl 449 + 450 + @lsTempSrcFl.setter 451 + def lsTempSrcFl(self, val): 452 + """ This setter so far is used to initialize self._lsTempSrcFl with a list """ 453 + self._lsTempSrcFl = val 454 + 455 + @property 456 + def lsBldFl(self) -> list: 457 + """ Get reference for self._lsBldFl """ 458 + return self._lsBldFl 459 + 460 + @lsBldFl.setter 461 + def lsBldFl(self, val): 462 + """ This setter so far is used only to reset self._lsBldFl """ 463 + self._lsBldFl = val 464 + 465 + @property 466 + def lsArchFl(self) -> list: 467 + """ Get reference for self._lsArchFl """ 468 + return self._lsArchFl 469 + 470 + @lsArchFl.setter 471 + def lsArchFl(self, val): 472 + """ This setter so far is used only to reset self._lsArchFl """ 473 + self._lsArchFl = val 474 + 475 + @property 476 + def lsArchPltDir(self) -> list: 477 + """ Get reference for self._lsArchPltDir """ 478 + return self._lsArchPltDir 479 + 480 + @lsArchPltDir.setter 481 + def lsArchPltDir(self, val): 482 + """ This setter so far is used only to reset self._lsArchPltDir """ 483 + self._lsArchPltDir = val 484 + 485 + class Workspace: 486 + """ 487 + @Description 488 + Extract/Store different files that 489 + are in every WS made with vitis >= v2023.2. 490 + """ 491 + 492 + def __init__(self): 493 + """ 494 + @Description 495 + Search and Store platforms, then applications, these functions should 496 + be linked with an attribute that will be added to <comp-settings>.json 497 + later, Applications[attr] <-> Platforms[attr]. #... 498 + 499 + Attributes self.sfWs and self.cfgWs hold data that needs to be copied/processed, 500 + from self.cfgWs different settings are preserved + references to <apps-dirname>. 501 + Both have setters/getters methods that are used to access various class dependent 502 + attributes (SrcFilesWS or ConfigWS) by reference, not redundant copies. 503 + """ 504 + self.sfWs = SrcFilesWS() 505 + # pattern vector; /i -> case insensitive; 506 + self.lsExcludedApps = [compile("fsbl", RegexFlag.IGNORECASE)] 507 + if UtilityWS.IS_DIRS: 508 + self.findPlatforms() 509 + # Set multiple Utility ... ? 'fa(), ...' 510 + # ~ Set ConfigWS paths for platforms too ~ 511 + self.cfgWs = ConfigWS() 512 + _lApps = self.findApplications() 513 + self.cfgWs.setApps(_lApps) 514 + LOG("All files have been collected!") 515 + 516 + def gatherAppSrcCd(self, 517 + pSrcFl : str, 518 + idxApp : int 519 + ): 520 + """ 521 + @Description 522 + Store in a list which is associated with an app, all the files 523 + that need to be copied to <sw-src>. srcFiles holds all the encountered 524 + header files for example. 525 + 526 + @Parameters 527 + pSrcFl: Path to src dir from <app-dir>. 528 + """ 529 + pSrcFlLoc = path.join(pSrcFl, SrcFilesWS.APP_SRCCODE) 530 + pCwd = getcwd() 531 + chdir(pSrcFlLoc) 532 + # Can store not just SrcFilesWS.lsSrcCpy '*.<some-extension>'. 533 + for item in SrcFilesWS.lsSrcCpy: 534 + srcFiles = list(Path(pSrcFlLoc).rglob(item)) 535 + if len(srcFiles) != UtilityWS.EMPTY_BUFFER: 536 + # [[]] - type 537 + self.sfWs.lsTempSrcFl[idxApp].append([str(itm) for itm in srcFiles]) 538 + # [[App1],[App2],[App3], ...], where App1,App2,App3 are other lists with 539 + # paths of source files that need to be copied. 540 + chdir(pCwd) 541 + 542 + def gatherAppOtherConf(self, 543 + pSrcFl : str, 544 + idxApp : int, 545 + repflOpt : bool = False 546 + ): 547 + """ 548 + @Description 549 + Files from SrcFilesWS.lsConfCpy are added to self.sfWs.lsTempSrcFl if 550 + they are found. Some are excluded with "slices" <idx-prefix> : <idx-suffix>. 551 + In some cases prefix/suffix are put directly as values, SrcFilesWS.lsConfCpy 552 + should be edited accordingly. 553 + 554 + @Parameters 555 + pSrcFl: Path to src dir from <app-dir>. 556 + idxApp: Index for an application component, lsTempSrcFl from 557 + sfWs stores all of them from workspace. 558 + repflOpt: By default it is on '0', this avoids storing 559 + files like .gitignore, but others can be added/ignored. 560 + """ 561 + if len(self.sfWs.lsTempSrcFl[idxApp]) != UtilityWS.EMPTY_BUFFER: 562 + # Source files should have been stored by now. 563 + if repflOpt: 564 + pGIgn = path.join(pSrcFl, SrcFilesWS.lsConfCpy[-1]) 565 + if path.exists(pGIgn) is True: 566 + self.sfWs.lsTempSrcFl[idxApp].append([pGIgn]) 567 + pSrcFlLoc = path.join(pSrcFl, SrcFilesWS.APP_SRCCODE) 568 + pCwd = getcwd() 569 + chdir(pSrcFlLoc) 570 + # Avoid build-sys file from first pos. 571 + for item in SrcFilesWS.lsConfCpy[SrcFilesWS.EXCLUDE_BSYSF_IDX + 1:-1]: 572 + srcFiles = list(Path(pSrcFlLoc).rglob(item)) 573 + if len(srcFiles) != UtilityWS.EMPTY_BUFFER: 574 + # [[]] - type 575 + self.sfWs.lsTempSrcFl[idxApp].append([str(itm) for itm in srcFiles]) 576 + chdir(pCwd) 577 + 578 + def processGatherFiles(self, 579 + idxApp : int, 580 + cmpFile : list, 581 + dJsonData : dict, 582 + pItem : str, 583 + lsDirApps : list 584 + ) -> int: 585 + """ 586 + @Description 587 + Filter Vitis applications files, gather source files + other configs, 588 + findApplications uses it, but functions should have a limited no. or lines. 589 + Check description from it. 590 + """ 591 + NOT_PATH = -1 592 + if (len(cmpFile) != UtilityWS.EMPTY_BUFFER and 593 + ((dJsonData["type"] == "HOST" or 594 + dJsonData["type"] == "HLS") or 595 + dJsonData["type"] == "UNKNOWN") 596 + ): 597 + # Associate application with its platform. 598 + appName = pItem[pItem.rfind(sep) + 1:] 599 + lHwPlt = dJsonData["platform"] 600 + # This idx has two uses, one for path like values in "platform" 601 + # and the second one if there is directly the name of platform. 602 + idxIfExXpfm = lHwPlt.rfind(".") 603 + # Path to .xpfm file only if it exists, can be used if it's -1 though 604 + idxPltName = lHwPlt.rfind(sep) 605 + if idxPltName == NOT_PATH and idxIfExXpfm == NOT_PATH: 606 + # Overwrite if necessary 607 + idxIfExXpfm = len(lHwPlt) 608 + # Pay attention which Utility object is used, bcs encJSON_Ws depends on it. 609 + relPathPlt = SrcFilesWS.APP_SRCCODE + sep + \ 610 + lHwPlt[idxPltName + 1:idxIfExXpfm] + sep + \ 611 + lHwPlt[idxPltName + 1:idxIfExXpfm] + ".xsa" 612 + self.cfgWs.utilCfgWs.dPltAppCorr[appName] = relPathPlt 613 + # Search for buid file. 614 + bFile = list(Path(pItem).rglob( 615 + SrcFilesWS.lsConfCpy[SrcFilesWS.BUILD_FILE_IDX])) 616 + # Just one element should be in the list. 617 + if len(bFile) != UtilityWS.EMPTY_BUFFER: 618 + lsDirApps.append(pItem) 619 + # Populate in SrcFilesWS scope, SrcFilesWS.BUILD_FILE_IDX or simply 0. 620 + self.sfWs.lsBldFl.append(path.join(pItem, str(bFile[SrcFilesWS.BUILD_FILE_IDX]))) 621 + self.sfWs.lsTempSrcFl.append([]) 622 + # Collect source files from <app-dir>/src. 623 + self.gatherAppSrcCd(pItem, idxApp) 624 + self.gatherAppOtherConf(pItem, idxApp) 625 + idxApp = idxApp + 1 626 + 627 + def findApplications(self) -> list: 628 + """ 629 + @Description 630 + Applications have a vitis-comp.json file that is checked to 631 + validate if it's platform or app. SrcFilesWS.lsConfCpy vector 632 + on idx=1 has predefined this file. It appears in <platform-dirname> 633 + too when an application is created by vitis. 634 + 635 + Path("<path>").rglob("<file-pattern>") searches in "<path>" all 636 + occurences of "<file-patter>". It returns a generator that can be 637 + casted to a vector/list obj. Therefore, indexing the wanted element, 638 + such as CMakeLists.txt or *.json. 639 + 640 + Apps are counted with idxApp and passed to self.gatherAppOtherConf, 641 + Some sort of correlation can be done to know which app has a certain 642 + platform. With a JSONDecoder, file-buffer is read then passed to 643 + <jsondecoder-obj>.decode func to get {[keys...] : [values...]} struct. 644 + """ 645 + IDX_VCOMP = 0 646 + self.sfWs.lsBldFl = [] 647 + # No intermediate dirs, levelDepth ~ 1; 648 + chdir(self.sfWs.appDir) 649 + # Store apps build files. 650 + lsDirApps = [] 651 + pCwd = getcwd() 652 + idxApp = 0 653 + for item in listdir(pCwd): 654 + if path.isdir(item) is False or item.startswith("."): continue 655 + # Get build file ~ maybe check if it exists ? 656 + # Check for vitis-comp.json or other files specific to an application. 657 + pItem = path.join(pCwd, item) 658 + cmpFile = list(Path(pItem).rglob( 659 + SrcFilesWS.lsConfCpy[SrcFilesWS.COMP_FILE_IDX])) 660 + if len(cmpFile) == UtilityWS.EMPTY_BUFFER: continue 661 + strCmpFile = str(cmpFile[IDX_VCOMP]) 662 + # Extract type of component; this can be moved to UtilityWS. 663 + # Extras: An app can have multiple templates though, but vitis-py-tools bugs 664 + # prevent it from having them set, except <hello-world>. 665 + dJsonData = JSONDecoder().decode(open(strCmpFile).read()) 666 + # For now just one type of application is needed to not be saved. 667 + mtName = self.lsExcludedApps[0].search(dJsonData["name"]) 668 + if mtName is not None: continue 669 + # Pass parameters by ref with the same names. 670 + iRet = self.processGatherFiles(idxApp, cmpFile, dJsonData, pItem, lsDirApps) 671 + # Get back to 'sw submodule'. 672 + chdir(self.sfWs.pSubSw) 673 + LOG("Number of applications found: " + str(len(lsDirApps))) 674 + return lsDirApps 675 + 676 + def findPlatforms(self): 677 + """ 678 + @Description 679 + Working dir when this func is called must be sw submodule. Anyway, 680 + sw structure had been verified long before calling findPlatforms. 681 + Iterate over all content of <ws> to find *.xsa file(s). Only the first 682 + file found is stored in self.sfWs.lsArchFl, <platform-dirname> into 683 + self.sfWs.lsArchPltDir respectively. 684 + """ 685 + IDX_FRENC = 0 686 + self.sfWs.lsArchFl, self.sfWs.lsArchPltDir = [], [] 687 + chdir(self.sfWs.appDir) 688 + pCwd = getcwd() 689 + for item in listdir(pCwd): 690 + if path.isdir(item) is False or item.startswith("."): continue 691 + # Get handoff ~ can be more; 692 + pItem = path.join(pCwd, item) 693 + archFile = list(Path(pItem).rglob(SrcFilesWS.HOFF_HDL)) 694 + # Just one element should be in the list. 695 + # Maybe check for vitis-comp.json or other files specific to a platform ? 696 + if len(archFile) != UtilityWS.EMPTY_BUFFER: 697 + # Populate with xsa files path. 698 + self.sfWs.lsArchFl.append(str(archFile[IDX_FRENC])) 699 + # Preserve platforms dirs. 700 + self.sfWs.lsArchPltDir.append(item) 701 + # Get back to 'sw submodule'. 702 + chdir(self.sfWs.pSubSw) 703 + LOG("Number of platforms found: " + str(len(self.sfWs.lsArchPltDir))) 704 + 705 + def checkInSF(self) -> int: 706 + """ 707 + @Description 708 + Just one obj to Workspace class is needed to collect/prepare 709 + source/config files that will be copied with collectCpyFiles func. 710 + 711 + Ideal structure of sw submodule: 712 + ++++++++++++++++++++++++++++++++++++++++++++ 713 + + sw + 714 + + |- src + 715 + + |- <checked-in-platforms-dirs> + 716 + + |- <checked-in-applications-dirs> + 717 + + |- scripts + 718 + + |- __pychace__ + 719 + + |- <precompiled-py-files> + 720 + + |- checkin.py + 721 + + |- checkout.py + 722 + + |- <other-files> + 723 + + |- ws + 724 + + |- <platform-dirs> + 725 + + |- ... <specific-files> + 726 + + |- <application-dirs> + 727 + + |- ... <specific-files> + 728 + + |- <other-files> + 729 + ++++++++++++++++++++++++++++++++++++++++++++ 730 + """ 731 + if not UtilityWS.IS_DIRS: 732 + return UtilityWS.FAILURE 733 + iRet = self.sfWs.collectCpyFiles(self.cfgWs.refLApps) 734 + iRet = self.cfgWs.utilCfgWs.encJSON_Ws(self.cfgWs.bdRes, locations=self.cfgWs.refLApps) 735 + UtilityWS.srvCl.stop() 736 + # Clean up .wsdata after vitis-server shutdown if it exists. 737 + return iRet 738 + 739 + if __name__ == "__main__": 740 + """ 741 + @Description 742 + This ~file~ can be used as a module or standalone 743 + py program. From a cmd-line: `vitis -s [<relative-or-absolute-path>]checkin.py`, 744 + where is the current directory from terminal process does not influence behavior 745 + of the above functionalities. 746 + """ 747 + lcWs = Workspace() 748 + iRet = lcWs.checkInSF() 749 + LOG("Check in file finished with status: " + str(iRet))
+406
sw/scripts/checkout.py
··· 1 + 2 + """ 3 + Company: Digilent RO 4 + Engineers: rb & bs 5 + Usage: for vitis projects (>= v2023.2) 6 + 7 + @Description 8 + This checkout.py has the same behavior 9 + as the previous checkout.tcl. It creates 10 + from sw -> src multiple applications into 11 + sw -> ws. 12 + 13 + @Insights 14 + Vitis v2024.1 has Python v3.8.3. 15 + """ 16 + from vitis import create_client, dispose 17 + import time 18 + from datetime import datetime 19 + import shutil 20 + from re import search 21 + from json import JSONDecoder 22 + from os import (path, getcwd, walk, 23 + sep, listdir, unlink 24 + ) 25 + import hsi 26 + import xsdb 27 + import sys 28 + 29 + class Workspace: 30 + """ 31 + @Description 32 + Resources to set app/domain configs, and create multiple applications. 33 + """ 34 + SUCCESS = 0 35 + FAILURE = -1 36 + COMP_SETTINGS = "comp-settings.json" 37 + DEBUG = 0 38 + 39 + def __init__(self): 40 + pass 41 + 42 + def setConfigDomain(self, 43 + domain, 44 + option : str, 45 + **kargs 46 + ) -> int: 47 + """ 48 + @Description 49 + Iterate over kargs : dict elements and set domain configs. 50 + 51 + @Parameters 52 + domain: domain name of current workspace. 53 + option: for processor or OS. 54 + kargs: dict with {[params...] : [values...]}. 55 + """ 56 + for key, value in kargs.items(): 57 + try: 58 + domain.set_config(option=option, param=key, value=value) 59 + # return Workspace.SUCCESS 60 + except: 61 + print(f"ERROR: Failed to set config param {key} for processor!") 62 + # Cannot set all params... 63 + # return Workspace.FAILURE 64 + # Even though set_config fails. 65 + return Workspace.SUCCESS 66 + 67 + def setConfigApp(self, 68 + app, 69 + **kargs 70 + ) -> int: 71 + """ 72 + @Description 73 + Iterate over kargs : dict elements and set app configs. 74 + 75 + @Parameters 76 + app: current application obj. 77 + kargs: dict with {[params...] : [values...]}. 78 + """ 79 + for key, value in kargs.items(): 80 + try: 81 + app.set_app_config(key=key, value=value) 82 + # return Workspace.SUCCESS 83 + except: 84 + print(f"ERROR: Failed to set config param {key} for processor!") 85 + # Cannot set all params... 86 + # return Workspace.FAILURE 87 + return Workspace.SUCCESS 88 + 89 + def decJSON_Ws(self, 90 + app, 91 + appname : str, 92 + filepath="" 93 + ) -> int: 94 + """ 95 + @Description 96 + Set all User config from a custom file created at check in workflow. 97 + 98 + @Parameters 99 + app: obj returned by create_application_component function from vitis.cli_client. 100 + appname: name found in json file (last key) or it can be put manually. 101 + filepath: comp-setting.json path. 102 + """ 103 + dJsonStruct = JSONDecoder().decode(open(filepath).read()) 104 + for key, value in dJsonStruct.items(): 105 + if (appname != key and 106 + len(value) != 0 and 107 + key != "USER_UNDEFINED_SYMBOLS" 108 + ): 109 + app.set_app_config(key, value) 110 + return Workspace.SUCCESS 111 + 112 + def checkOutSF(self) -> int: 113 + def get_metadata(**kwargs): 114 + xsa = "" 115 + open_xsa = 0 116 + ret_metadata = {'arch' : '', 'target_proc' : ''} 117 + for key, value in kwargs.items(): 118 + if key == "xsa": 119 + xsa = value 120 + if key == "open_xsa": 121 + open_xsa = 1 122 + 123 + if open_xsa == 1: 124 + if xsa != "": 125 + print("Info: Using XSA file: " + xsa + " to extract HW metadata using HSI Python API") 126 + HwDesign = hsi.HwManager.open_hw_design(xsa) 127 + ret_metadata['arch'] = HwDesign.FAMILY 128 + for proc in HwDesign.get_cells(hierarchical='true',filter='IP_TYPE==PROCESSOR'): 129 + if proc.IP_NAME == "psu_cortexa53" or proc.IP_NAME == "psu_cortexa72" or proc.IP_NAME == "ps7_cortexa9": 130 + ret_metadata['target_proc'] = proc.IP_NAME+"_0" 131 + break 132 + #HwDesign.close() 133 + else: 134 + print("Error: No XSA passed. HW metadata will not be extracted.") 135 + else: 136 + print("Info: no need to open XSA") 137 + 138 + return ret_metadata 139 + """ 140 + @Description 141 + ... 142 + 143 + TODO: 144 + Find and extract xsa metadata with py-vitis/hsi resources for 145 + cpu, os to configure domain. Use more pystd lib functions to 146 + some parts of this file more efficient. 147 + """ 148 + dispose() 149 + 150 + print("\n---------------------------------------------------------") 151 + print(" Checking out Vitis project to Vitis Unified IDE ") 152 + print("---------------------------------------------------------") 153 + client = create_client() 154 + script_path = path.dirname(path.abspath(__file__)) 155 + if Workspace.DEBUG: 156 + date = datetime.now().strftime("%Y%m%d%I%M%S") 157 + # Strip out cwd which is ~scripts~. 158 + ws_path = script_path[:script_path.rfind(sep)] + f"{sep}ws" + f"_{date}" 159 + else: 160 + # Strip out cwd which is ~scripts~. 161 + ws_path = script_path[:script_path.rfind(sep)] + f"{sep}ws" 162 + repo_path = script_path[:script_path.rfind(sep)] + sep + 'repo' 163 + # Delete the workspace if it already exists. 164 + max_try = 10 165 + for attempt in range(max_try): 166 + try: 167 + shutil.rmtree(ws_path) 168 + print(f"Deleted workspace {ws_path} on attempt: {attempt+1}.") 169 + break 170 + except FileNotFoundError: 171 + print("Old workspace folder was already deleted or does not exist. The checkout script will continue to run unimpeded.") 172 + break 173 + except Exception as e: 174 + print(f"Attempt {attempt+1} failed: {e}") 175 + else: 176 + raise Exception(f"Failed to delete old workspace. Please delete it manually before running the checkout script one more time.") 177 + client.set_workspace(ws_path) 178 + print("Successfully created Vitis client on workspace {}".format(client.get_workspace())) 179 + app_names = [] 180 + hw_platforms = [] 181 + hw_pf_paths = [] 182 + for dirpath, dirnames, filenames in walk(script_path[:script_path.rfind(sep)] + f"{sep}src"): 183 + print(filenames) 184 + for dirname in dirnames: 185 + if search(r"src", dirname): 186 + print(dirpath) 187 + application_name = path.basename(dirpath) 188 + print(application_name) 189 + print(f"this is the name of the project: {application_name}") 190 + app_names.append(application_name) 191 + print(app_names) 192 + match = search(r"src\.+", dirpath) 193 + print(match) 194 + for filename in filenames: 195 + if filename.endswith(".xsa"): 196 + file = path.join(dirpath, filename) 197 + print(f"Found - {file}") 198 + print(f"xsa dirpath = {dirpath}") 199 + xsa_dirpath = dirpath 200 + hw_pf_paths.append(xsa_dirpath) 201 + print(f"xsa dirname = {path.basename(xsa_dirpath)}") 202 + xsa_dirpath_name = path.basename(xsa_dirpath) 203 + hw_platforms.append(xsa_dirpath_name) 204 + print(f"\nDetected one or more applications present: {app_names}") 205 + print(f"Detected one or more hardware platforms present: {hw_platforms}") 206 + print(hw_pf_paths) 207 + 208 + ret_metadata = {"arch" : "", "target_proc" : ""} 209 + 210 + start_time = time.time() 211 + 212 + arch_and_cpu_metadata = get_metadata(xsa=file, open_xsa="1") 213 + 214 + arch = arch_and_cpu_metadata['arch'] 215 + 216 + if arch in ('spartan7', 'artix7', 'kintex7'): 217 + target_proc = 'microblaze_0' 218 + else: 219 + target_proc = arch_and_cpu_metadata['target_proc'] 220 + 221 + print("Info: Detected arch: " + arch) 222 + print("Info: Using target processor: " + target_proc) 223 + 224 + # List all files and directories in the given path 225 + # Remove all files that result from get_metadata() unzipping the xsa 226 + for xsa_path in hw_pf_paths: 227 + print(listdir(xsa_path)) 228 + for filename in listdir(xsa_path): 229 + if not filename.endswith(".xsa"): 230 + file_path = path.join(xsa_path, filename) 231 + try: 232 + if path.isfile(file_path) or path.islink(file_path): 233 + unlink(file_path) # Remove file or symbolic link 234 + elif path.isdir(file_path): 235 + shutil.rmtree(file_path) # Remove directory and its contents 236 + except Exception as e: 237 + print(f'Failed to delete {file_path}. Reason: {e}') 238 + 239 + end_time = time.time() 240 + # Measure execution time 241 + execution_time = end_time - start_time 242 + print(f"Execution time: {execution_time:.4f} seconds") 243 + print(f"\nProcessor device family is: {arch}") 244 + 245 + if arch in ('spartan7', 'artix7', 'kintex7'): 246 + print("Creating platform component " + xsa_dirpath_name + ".") 247 + platform = client.create_platform_component( 248 + name=xsa_dirpath_name, 249 + hw_design=file, 250 + no_boot_bsp=True 251 + ) 252 + platform.update_desc(desc=xsa_dirpath_name) 253 + print(f"Adding new domain \"domain_{target_proc}\" for cpu: \"{target_proc}\" and OS: \"standalone\"") 254 + domain = platform.add_domain( 255 + cpu=target_proc, 256 + os="standalone", 257 + name=f"domain_{target_proc}", 258 + display_name=f"domain_{target_proc}", 259 + support_app = "hello_world" 260 + ) 261 + print(f"Configuring the domain \"domain_{target_proc}\"...") 262 + print(f"BSP settings for the domain \"domain_{target_proc}\"") 263 + # Setting config params for processor and os. 264 + self.setConfigDomain( 265 + domain, 266 + "proc", 267 + proc_extra_compiler_flags="-g -ffunction-sections -fdata-sections -Wall -Wextra", 268 + proc_xmdstub_peripheral="none", 269 + proc_archiver="mb-ar", 270 + proc_dependency_flags="-MMD -MP", 271 + proc_assembler="mb-as", 272 + proc_compiler_flags="-O2 -c", 273 + proc_compiler="mb-gcc" 274 + ) 275 + self.setConfigDomain( 276 + domain, 277 + "os", 278 + standalone_microblaze_exceptions="false", 279 + standalone_stdin="axi_uartlite_0", 280 + standalone_ttc_select_cntr="2", 281 + standalone_stdout="axi_uartlite_0", 282 + standalone_predecode_fpu_exceptions="false", 283 + standalone_sleep_timer="none", 284 + standalone_enable_sw_intrusive_profiling="false", 285 + standalone_hypervisor_guest="false", 286 + standalone_clocking="false", 287 + standalone_zynqmp_fsbl_bsp="false", 288 + standalone_lockstep_mode_debug="false", 289 + standalone_profile_timer="none" 290 + ) 291 + else: 292 + print("Creating platform component " + xsa_dirpath_name + ".") 293 + platform = client.create_platform_component( 294 + name=xsa_dirpath_name, 295 + hw_design=file 296 + ) 297 + platform.update_desc(desc=xsa_dirpath_name) 298 + print(f"Adding new domain \"domain_{target_proc}\" for cpu: \"{target_proc}\" and OS: \"standalone\"") 299 + domain = platform.add_domain( 300 + cpu=target_proc, 301 + os="standalone", 302 + name=f"domain_{target_proc}", 303 + display_name=f"domain_{target_proc}", 304 + support_app = "hello_world" 305 + ) 306 + print(f"Configuring the domain \"domain_{target_proc}\"...") 307 + print(f"BSP settings for the domain \"domain_{target_proc}\"") 308 + platform.build() 309 + print("\n") 310 + 311 + if arch == "zynquplus": 312 + embeddedsw = client.set_embedded_sw_repo(level = 'LOCAL', path = [repo_path]) 313 + print(f"Adding new domain '{target_proc}_domain_fsbl' for cpu: '{target_proc}' and OS: 'standalone'") 314 + zynqmp_fsbl_domain = platform.add_domain(cpu = target_proc, os = 'standalone', name = f'{target_proc}_domain_fsbl', display_name = f'{target_proc}_domain_fsbl', support_app = "zynqmp_fsbl") 315 + platform.build() 316 + #Generating custom fsbl application from template 317 + fsbl_app = client.create_app_component( 318 + name='ZynqMP_FSBL', 319 + platform=client.get_workspace() + sep + 320 + xsa_dirpath_name + sep + 321 + "export" + sep + 322 + xsa_dirpath_name + sep + 323 + xsa_dirpath_name + ".xpfm", 324 + domain=f"{target_proc}_domain_fsbl", 325 + template="zynqmp_fsbl" 326 + ) 327 + #platforms = client.list_platform_components() 328 + print(f'Platform is located at: {script_path[:script_path.rfind(sep)] + sep + xsa_dirpath_name}') 329 + fsbl_app.import_files( 330 + from_loc=client.get_workspace() + sep + xsa_dirpath_name + sep + 'hw' + sep + 'sdt', 331 + files= ['psu_init.c', 'psu_init.h'], 332 + dest_dir_in_cmp="src" 333 + ) 334 + fsbl_app.build() 335 + platform.remove_boot_bsp() 336 + platform.set_fsbl_elf(path = fsbl_app.component_location + sep + 'build' + sep + 'ZynqMP_FSBL.elf') 337 + platform.build() 338 + for app_name in app_names: 339 + print(f"Creating application component {app_name}") 340 + app = client.create_app_component( 341 + name=app_name, 342 + platform=client.get_workspace() + sep + 343 + xsa_dirpath_name + sep + 344 + "export" + sep + 345 + xsa_dirpath_name + sep + 346 + xsa_dirpath_name + ".xpfm", 347 + domain=f"domain_{target_proc}" if arch not in ('spartan7', 'artix7', 'kintex7') else "domain_microblaze_0", 348 + template='empty_application' 349 + ) 350 + # Extract saved settings. 351 + iRet = self.decJSON_Ws( 352 + app, 353 + appname=app_name, 354 + filepath=script_path[:script_path.rfind(sep)] + sep + 355 + "src" + sep + 356 + app_name + sep + 357 + Workspace.COMP_SETTINGS 358 + ) 359 + """ 360 + iRet = self.setConfigApp( 361 + app, 362 + USER_COMPILE_DEFINITIONS=["DEBUG"], 363 + USER_COMPILE_DEBUG_LEVEL=["-g3"], 364 + USER_LINK_LIBRARIES=["m"] 365 + ) 366 + if(mcu.deviceFamily == "zynq"): 367 + iRet = self.setConfigApp( 368 + app, 369 + USER_COMPILE_OTHER_FLAGS="-fmessage-length=0 -MT\"$$@\" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard", 370 + USER_LINK_OTHER_FLAGS="-mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -Wl,-build-id=none" 371 + ) 372 + """ 373 + app.import_files( 374 + from_loc=script_path[:script_path.rfind(sep)] + sep + "src" + sep + app.component_name + sep + "src", 375 + dest_dir_in_cmp="src" 376 + ) 377 + print(f"\nApp component location: {app.component_location}\n") 378 + # Removing files generated by the previous template. 379 + for dirpath, dirnames, filenames in walk(app.component_location + sep + "src"): 380 + print(filenames) 381 + for filename in filenames: 382 + if (filename in ('Xilinx.spec', 'README.txt')): 383 + print(f"\nRemoving {filename} from {path.join(dirpath, filename)}") 384 + app.remove_files(files=[app.component_location + sep + "src" + sep + filename]) 385 + # Removing tcl files that should not be there. 386 + for dirpath, dirnames, filenames in walk(app.component_location + sep + "_ide"+ sep + "psinit"): 387 + print("") 388 + print(filenames) 389 + for filename in filenames: 390 + if (filename not in ('psu_init.tcl', 'ps7_init.tcl')): 391 + print(f"\nRemoving {filename} from {path.join(dirpath, filename)}") 392 + app.remove_files(files=[app.component_location + sep + "_ide" + sep + "psinit" + sep + filename]) 393 + app.build() 394 + dispose() 395 + return Workspace.SUCCESS 396 + 397 + if __name__ == "__main__": 398 + """ 399 + @Description 400 + This ~file~ can be used as a module or standalone 401 + py program. From a cmd-line: `vitis -s [<relative-or-absolute-path>]checkout.py`, 402 + where is the current directory from terminal process does not influence behavior 403 + of the above functionalities. 404 + """ 405 + lcWs = Workspace() 406 + iRet = lcWs.checkOutSF()
+28
sw/scripts/cleanup.cmd
··· 1 + @echo off 2 + rem save current working directory 3 + pushd %~dp0 4 + 5 + rem delete all files from subfolders 6 + for /d /r %%i in (*) do del /f /q %%i\* 7 + rem delete all subfolders 8 + for /d %%i in (*) do rd /S /Q %%i 9 + 10 + rem unmark read only from all files 11 + attrib -R .\* /S 12 + 13 + rem mark read only those we wish to keep 14 + attrib +R .\cleanup.sh 15 + attrib +R .\cleanup.cmd 16 + attrib +R .\checkin.py 17 + attrib +R .\checkout.py 18 + attrib +R .\LICENSE 19 + attrib +R .\README.md 20 + 21 + rem delete all non read-only 22 + del /Q /A:-R .\* 23 + 24 + rem unmark read-only 25 + attrib -R .\* 26 + 27 + rem restore original working directory 28 + popd
+21
sw/scripts/cleanup.sh
··· 1 + # This script is useful for cleaning up the 'project' 2 + # directory of a Digilent Vitis-project git repository 3 + ### 4 + # Run the following command to change permissions of 5 + # this 'cleanup' file if needed: 6 + # chmod u+x cleanup.sh 7 + ### 8 + 9 + script_dir=$(dirname ${BASH_SOURCE[0]}) 10 + 11 + # Remove directories/subdirectories 12 + find $script_dir -mindepth 1 -type d -exec rm -rf {} + 13 + 14 + # Remove any other files than: 15 + find $script_dir -type f ! -name 'cleanup.sh' \ 16 + ! -name 'cleanup.cmd' \ 17 + ! -name 'checkin.py' \ 18 + ! -name 'checkout.py' \ 19 + ! -name 'LICENSE' \ 20 + ! -name 'README.md' \ 21 + -exec rm -rf {} +
+94
sw/scripts/misc.py
··· 1 + 2 + from ctypes import cdll 3 + from logging import (Logger, INFO, StreamHandler, 4 + Formatter) 5 + from sys import stdout 6 + 7 + FNEXIST = 1 8 + FNOPEN = 2 9 + FOPEN = 3 10 + FLOCKERR = 4 11 + 12 + def LOG(msg="", 13 + format="%(asctime)s %(levelname)s : %(message)s", 14 + ): 15 + """ 16 + @Description 17 + Custom logging mechanism for displaying informations during 18 + the execution of check in workflow. 19 + 20 + @Parameters 21 + msg: message to display to stdout 22 + format: default format: time - level name - actual message 23 + """ 24 + class _LOG(Logger): 25 + """ 26 + Simple layout class for logging 27 + """ 28 + def __init__(self, msg, fmt, name="Info Checkin", stream=stdout): 29 + super().__init__(name=name, level=INFO) 30 + self.sHnd = StreamHandler(stream) 31 + self.message = msg 32 + self._formater = Formatter(fmt) 33 + self.sHnd.setFormatter(self._formater) 34 + self.addHandler(self.sHnd) 35 + self.log(level=INFO, msg=self.message) 36 + # Nested log 37 + _locLog = _LOG(msg, format) 38 + 39 + def CkFileOpenBlock(filename : str, 40 + osName="" 41 + ) -> int: 42 + """ 43 + @Description 44 + Options for file management on win are found at 45 + win32 -> fileio -> file-management-functions on win website. For lnx, 46 + on man-pages -> man0 -> fcnt.h. The `.lock` file is assumed to be in 47 + workspace root dir. 48 + """ 49 + # Check if file exits. 50 + if not access(filename, F_OK): 51 + # File doesn't exist. 52 + return UtilityWS.FNEXIST 53 + 54 + if osName == "Windows": 55 + # Refs 56 + # _sopen_s = cdll.msvcrt._sopen_s 57 + _close = cdll.msvcrt._close 58 + _locking = cdll.msvcrt._locking 59 + _filelength = cdll.msvcrt._filelength 60 + # _get_errno = cdll.msvcrt._get_errno 61 + # Win CRT in general returns 0 if any error did not occur. 62 + _FSC = 0 63 + _LK_UNLCK = 0x0 64 + # _SH_DENYRW, _SH_NOPEN = 0x10, 0x11 65 + # _O_RDONLY, _S_IREAD = 0x0, 0x0100 66 + _O_RDONLY = 0x0 67 + # _SH_DENYWR = 0x20 68 + # _sopen 'gives back' a descriptor, but only -1; fHnd 69 + # erRet = _sopen_s(fHnd.value, filename, _O_RDONLY) 70 + with open(filename, "r") as lcFile: 71 + fHnd = lcFile.fileno() 72 + isRd = lcFile.readable() 73 + if isRd: 74 + # ln = _filelength(fHnd) 75 + _locking(fHnd, _LK_UNLCK, 0) 76 + _close(fHnd) 77 + # File is not opened by anyone else. 78 + return UtilityWS.FNOPEN 79 + elif osName == "Linux" or osName == "Darwin": 80 + # This module comes only on Unix like platforms. 81 + from fcntl import (lockf, LOCK_UN) 82 + # Get file descriptor. 83 + with open(filename, "r") as lcFile: 84 + lcFd = lcFile.fileno() 85 + # Unlock file directly. 86 + try: 87 + lockf(lcFd, LOCK_UN, SEEK_END) 88 + return UtilityWS.FNOPEN 89 + except OSError as err: 90 + # Interpret error from lockf in some way. 91 + LOG(msg=f"{err.__cause__}" + f"{err.__context__}") 92 + return UtiltyWS.FLOCKERR 93 + else: 94 + LOG("This OS: " + osName + " is not supported!")
+52
sw/src/Zybo-Z7-20-pcam-5c/comp-settings.json
··· 1 + 2 + { 3 + "USER_COMPILE_DEFINITIONS" : [ 4 + "DEBUG" 5 + ], 6 + "USER_UNDEFINED_SYMBOLS" : [ 7 + "\"__clang__\"" 8 + ], 9 + "USER_INCLUDE_DIRECTORIES" : [], 10 + "USER_COMPILE_SOURCES" : [ 11 + "\"main.cc\"" 12 + ], 13 + "USER_COMPILE_WARNINGS_ALL" : [ 14 + "-Wall" 15 + ], 16 + "USER_COMPILE_WARNINGS_EXTRA" : [ 17 + "-Wextra" 18 + ], 19 + "USER_COMPILE_WARNINGS_AS_ERRORS" : [], 20 + "USER_COMPILE_WARNINGS_CHECK_SYNTAX_ONLY" : [], 21 + "USER_COMPILE_WARNINGS_PEDANTIC" : [], 22 + "USER_COMPILE_WARNINGS_PEDANTIC_AS_ERRORS" : [], 23 + "USER_COMPILE_WARNINGS_INHIBIT_ALL" : [], 24 + "USER_COMPILE_OPTIMIZATION_LEVEL" : [ 25 + "-O0" 26 + ], 27 + "USER_COMPILE_OPTIMIZATION_OTHER_FLAGS" : [], 28 + "USER_COMPILE_DEBUG_LEVEL" : [ 29 + "-g3" 30 + ], 31 + "USER_COMPILE_DEBUG_OTHER_FLAGS" : [], 32 + "USER_COMPILE_VERBOSE" : [], 33 + "USER_COMPILE_ANSI" : [], 34 + "USER_COMPILE_OTHER_FLAGS" : [ 35 + "\"-fmessage-length=0 -MT\"$$@\" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard\"" 36 + ], 37 + "USER_LINK_NO_START_FILES" : [], 38 + "USER_LINK_NO_DEFAULT_LIBS" : [], 39 + "USER_LINK_NO_STDLIB" : [], 40 + "USER_LINK_OMIT_ALL_SYMBOL_INFO" : [], 41 + "USER_LINK_LIBRARIES" : [ 42 + "m" 43 + ], 44 + "USER_LINK_DIRECTORIES" : [], 45 + "USER_LINKER_SCRIPT" : [ 46 + "\"${CMAKE_SOURCE_DIR}/lscript.ld\"" 47 + ], 48 + "USER_LINK_OTHER_FLAGS" : [ 49 + "\"-mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -Wl,-build-id=none\"" 50 + ], 51 + "Zybo-Z7-20-pcam-5c" : "src\\system_wrapper\\system_wrapper.xsa" 52 + }
+101
sw/src/Zybo-Z7-20-pcam-5c/src/CMakeLists.txt
··· 1 + # Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved. 2 + # SPDX-License-Identifier: MIT 3 + cmake_minimum_required(VERSION 3.16) 4 + 5 + include(${CMAKE_CURRENT_SOURCE_DIR}/Empty_applicationExample.cmake) 6 + include(${CMAKE_CURRENT_SOURCE_DIR}/UserConfig.cmake) 7 + set(APP_NAME Zybo-Z7-20-pcam-5c) 8 + project(${APP_NAME}) 9 + 10 + enable_language(C ASM CXX) 11 + find_package(common) 12 + collect(PROJECT_LIB_DEPS xilstandalone;xiltimer) 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 + 38 + 39 + 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 + 50 + 51 + 52 + 53 + 54 + 55 + 56 + 57 + 58 + collect(PROJECT_LIB_DEPS xil) 59 + collect(PROJECT_LIB_DEPS gcc) 60 + collect(PROJECT_LIB_DEPS c) 61 + 62 + collect (PROJECT_LIB_SOURCES main.cc) 63 + collect (PROJECT_LIB_SOURCES ov5640/OV5640.cpp) 64 + collect (PROJECT_LIB_SOURCES platform.c) 65 + collector_list (_sources PROJECT_LIB_SOURCES) 66 + foreach (source ${_sources}) 67 + get_filename_component(ext ${source} EXT) 68 + list(APPEND src_ext ${ext}) 69 + endforeach() 70 + 71 + find_project_type ("${src_ext}" PROJECT_TYPE) 72 + 73 + if("${PROJECT_TYPE}" STREQUAL "c++") 74 + collect(PROJECT_LIB_DEPS stdc++) 75 + endif() 76 + collector_list (_deps PROJECT_LIB_DEPS) 77 + list (APPEND _deps ${USER_LINK_LIBRARIES}) 78 + 79 + if("${PROJECT_TYPE}" STREQUAL "c++") 80 + string (REPLACE ";" ",-l" _deps "${_deps}") 81 + endif() 82 + if(CMAKE_EXPORT_COMPILE_COMMANDS) 83 + set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) 84 + set(CMAKE_C_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}) 85 + endif() 86 + linker_gen("${CMAKE_CURRENT_SOURCE_DIR}/linker_files/") 87 + string(APPEND CMAKE_C_FLAGS ${USER_COMPILE_OPTIONS}) 88 + string(APPEND CMAKE_CXX_FLAGS ${USER_COMPILE_OPTIONS}) 89 + string(APPEND CMAKE_C_LINK_FLAGS ${USER_LINK_OPTIONS}) 90 + string(APPEND CMAKE_CXX_LINK_FLAGS ${USER_LINK_OPTIONS}) 91 + add_dependency_on_bsp(_sources) 92 + add_executable(${APP_NAME}.elf ${_sources}) 93 + set_target_properties(${APP_NAME}.elf PROPERTIES LINK_DEPENDS ${USER_LINKER_SCRIPT}) 94 + target_link_libraries(${APP_NAME}.elf -Wl,-T -Wl,\"${USER_LINKER_SCRIPT}\" -L\"${CMAKE_SOURCE_DIR}/\" -L\"${CMAKE_LIBRARY_PATH}/\" -L\"${USER_LINK_DIRECTORIES}/\" -Wl,--start-group,-l${_deps} -Wl,--end-group) 95 + target_compile_definitions(${APP_NAME}.elf PUBLIC ${USER_COMPILE_DEFINITIONS}) 96 + target_include_directories(${APP_NAME}.elf 97 + PUBLIC ${USER_INCLUDE_DIRECTORIES} 98 + "../../system_wrapper/hw/sdt/drivers/MIPI_D_PHY_RX_v1_0/src/" 99 + "../../system_wrapper/hw/sdt/drivers/MIPI_CSI_2_RX_v1_0/src/" 100 + ) 101 + print_elf_size(CMAKE_SIZE ${APP_NAME})
+16
sw/src/Zybo-Z7-20-pcam-5c/src/Empty_applicationExample.cmake
··· 1 + set(ps7_ddr_0_memory_0 "0x100000;0x3ff00000") 2 + set(ps7_ram_0_memory_0 "0x0;0x30000") 3 + set(ps7_ram_1_memory_1 "0xffff0000;0xfe00") 4 + set(DDR ps7_ddr_0_memory_0) 5 + set(CODE ps7_ddr_0_memory_0) 6 + set(DATA ps7_ddr_0_memory_0) 7 + set(TOTAL_MEM_CONTROLLERS "ps7_ddr_0_memory_0;ps7_ram_0_memory_0;ps7_ram_1_memory_1") 8 + set(MEMORY_SECTION "MEMORY 9 + { 10 + ps7_ddr_0_memory_0 : ORIGIN = 0x100000, LENGTH = 0x3ff00000 11 + ps7_qspi_linear_0_memory_0 : ORIGIN = 0xfc000000, LENGTH = 0x1000000 12 + ps7_ram_0_memory_0 : ORIGIN = 0x0, LENGTH = 0x30000 13 + ps7_ram_1_memory_1 : ORIGIN = 0xffff0000, LENGTH = 0xfe00 14 + }") 15 + set(STACK_SIZE 0x2000) 16 + set(HEAP_SIZE 0x2000)
+164
sw/src/Zybo-Z7-20-pcam-5c/src/UserConfig.cmake
··· 1 + # Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved. 2 + # SPDX-License-Identifier: MIT 3 + cmake_minimum_required(VERSION 3.16) 4 + 5 + ### USER SETTINGS START ### 6 + # Below settings can be customized 7 + # User need to edit it manually as per their needs. 8 + ### DO NOT ADD OR REMOVE VARIABLES FROM THIS SECTION ### 9 + # ----------------------------------------- 10 + # Add any compiler definitions, they will be added as extra definitions 11 + # Example adding VERBOSE=1 will pass -DVERBOSE=1 to the compiler. 12 + set(USER_COMPILE_DEFINITIONS 13 + DEBUG 14 + ) 15 + 16 + # Undefine any previously specified compiler definitions, either built in or provided with a -D option 17 + # Example adding MY_SYMBOL will pass -UMY_SYMBOL to the compiler. 18 + set(USER_UNDEFINED_SYMBOLS 19 + "__clang__" 20 + ) 21 + 22 + 23 + # Add any directories below, they will be added as extra include directories. 24 + # Example 1: Adding /proj/data/include will pass -I/proj/data/include 25 + # Example 2: Adding ../../common/include will consider the path as relative to this component directory. 26 + # Example 3: Adding ${CMAKE_SOURCE_DIR}/data/include to add data/include from this project. 27 + 28 + set(USER_INCLUDE_DIRECTORIES 29 + ) 30 + set(USER_COMPILE_SOURCES 31 + "main.cc" 32 + "platform.c" 33 + "OV5640.cpp" 34 + ) 35 + 36 + # ----------------------------------------- 37 + 38 + # Turn on all optional warnings (-Wall) 39 + set(USER_COMPILE_WARNINGS_ALL -Wall) 40 + 41 + # Enable extra warning flags (-Wextra) 42 + set(USER_COMPILE_WARNINGS_EXTRA -Wextra) 43 + 44 + # Make all warnings into hard errors (-Werror) 45 + set(USER_COMPILE_WARNINGS_AS_ERRORS ) 46 + 47 + # Check the code for syntax errors, but don't do anything beyond that. (-fsyntax-only) 48 + set(USER_COMPILE_WARNINGS_CHECK_SYNTAX_ONLY ) 49 + 50 + # Issue all the mandatory diagnostics listed in the C standard (-pedantic) 51 + set(USER_COMPILE_WARNINGS_PEDANTIC ) 52 + 53 + # Issue all the mandatory diagnostics, and make all mandatory diagnostics into errors. (-pedantic-errors) 54 + set(USER_COMPILE_WARNINGS_PEDANTIC_AS_ERRORS ) 55 + 56 + # Suppress all warnings (-w) 57 + set(USER_COMPILE_WARNINGS_INHIBIT_ALL ) 58 + 59 + # ----------------------------------------- 60 + 61 + # Optimization level "-O0" [None] , "-O1" [Optimize] , "-O2" [Optimize More], "-O3" [Optimize Most] or "-Os" [Optimize Size] 62 + set(USER_COMPILE_OPTIMIZATION_LEVEL -O0) 63 + 64 + # Other flags related to optimization 65 + set(USER_COMPILE_OPTIMIZATION_OTHER_FLAGS ) 66 + 67 + # ----------------------------------------- 68 + 69 + # Debug level "" [None], "-g1" [Minimum], "g2" [Default], "g3" [Maximim] 70 + set(USER_COMPILE_DEBUG_LEVEL -g3) 71 + 72 + # Other flags releated to debugging 73 + set(USER_COMPILE_DEBUG_OTHER_FLAGS ) 74 + 75 + # ----------------------------------------- 76 + 77 + # Enable Profiling (-pg) (This feature is not supported currently) 78 + # set(USER_COMPILE_PROFILING_ENABLE ) 79 + 80 + # ----------------------------------------- 81 + 82 + # Verbose (-v) 83 + set(USER_COMPILE_VERBOSE ) 84 + 85 + # Support ANSI_PROGRAM (-ansi) 86 + set(USER_COMPILE_ANSI ) 87 + 88 + # Add any compiler options that are not covered by the above variables, they will be added as extra compiler options 89 + # To enable profiling -pg [ for gprof ] or -p [ for prof information ] 90 + set(USER_COMPILE_OTHER_FLAGS "-fmessage-length=0 -MT"$$@" -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard") 91 + 92 + # ----------------------------------------- 93 + 94 + # Linker options 95 + # Do not use the standard system startup files when linking. 96 + # The standard system libraries are used normally, unless -nostdlib or -nodefaultlibs is used. (-nostartfiles) 97 + set(USER_LINK_NO_START_FILES ) 98 + 99 + # Do not use the standard system libraries when linking. (-nodefaultlibs) 100 + set(USER_LINK_NO_DEFAULT_LIBS ) 101 + 102 + # Do not use the standard system startup files or libraries when linking. (-nostdlib) 103 + set(USER_LINK_NO_STDLIB ) 104 + 105 + # Omit all symbol information (-s) 106 + set(USER_LINK_OMIT_ALL_SYMBOL_INFO ) 107 + 108 + 109 + # ----------------------------------------- 110 + 111 + # Add any libraries to be linked below, they will be added as extra libraries. 112 + # User need to update USER_LINK_DIRECTORIES below with these library paths. 113 + set(USER_LINK_LIBRARIES 114 + m 115 + ) 116 + 117 + # Add any directories to look for the libraries to be linked. 118 + # Example 1: Adding /proj/compression/lib will pass -L/proj/compression/lib to the linker. 119 + # Example adding Adding ../../common/lib will consider the path as relative to this directory. and will pass the path to -L option. 120 + set(USER_LINK_DIRECTORIES 121 + ) 122 + 123 + # ----------------------------------------- 124 + 125 + set(USER_LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/lscript.ld") 126 + 127 + # Add linker options to be passed, they will be added as extra linker options 128 + # Example : adding -s will pass -s to the linker. 129 + set(USER_LINK_OTHER_FLAGS 130 + "-mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard -Wl,-build-id=none" 131 + ) 132 + 133 + # ----------------------------------------- 134 + 135 + ### END OF USER SETTINGS SECTION ### 136 + ### DO NOT EDIT BEYOND THIS LINE ### 137 + 138 + set(USER_COMPILE_OPTIONS 139 + " ${USER_COMPILE_WARNINGS_ALL}" 140 + " ${USER_COMPILE_WARNINGS_EXTRA}" 141 + " ${USER_COMPILE_WARNINGS_AS_ERRORS}" 142 + " ${USER_COMPILE_WARNINGS_CHECK_SYNTAX_ONLY}" 143 + " ${USER_COMPILE_WARNINGS_PEDANTIC}" 144 + " ${USER_COMPILE_WARNINGS_PEDANTIC_AS_ERRORS}" 145 + " ${USER_COMPILE_WARNINGS_INHIBIT_ALL}" 146 + " ${USER_COMPILE_OPTIMIZATION_LEVEL}" 147 + " ${USER_COMPILE_OPTIMIZATION_OTHER_FLAGS}" 148 + " ${USER_COMPILE_DEBUG_LEVEL}" 149 + " ${USER_COMPILE_DEBUG_OTHER_FLAGS}" 150 + " ${USER_COMPILE_VERBOSE}" 151 + " ${USER_COMPILE_ANSI}" 152 + " ${USER_COMPILE_OTHER_FLAGS}" 153 + ) 154 + foreach(entry ${USER_UNDEFINED_SYMBOLS}) 155 + list(APPEND USER_COMPILE_OPTIONS " -U${entry}") 156 + endforeach() 157 + 158 + set(USER_LINK_OPTIONS 159 + " ${USER_LINKER_NO_START_FILES}" 160 + " ${USER_LINKER_NO_DEFAULT_LIBS}" 161 + " ${USER_LINKER_NO_STDLIB}" 162 + " ${USER_LINKER_OMIT_ALL_SYMBOL_INFO}" 163 + " ${USER_LINK_OTHER_FLAGS}" 164 + )
+190
sw/src/Zybo-Z7-20-pcam-5c/src/hdmi/VideoOutput.h
··· 1 + /* 2 + * VideoSource.h 3 + * 4 + * Created on: Aug 30, 2016 5 + * Author: Elod 6 + */ 7 + 8 + #ifndef VIDEOSOURCE_H_ 9 + #define VIDEOSOURCE_H_ 10 + 11 + #include <stdint.h> 12 + #include <stdexcept> 13 + #include <cstring> 14 + 15 + #include "xaxivdma.h" 16 + #include "xvtc.h" 17 + #include "xclk_wiz.h" 18 + 19 + #define STRINGIZE(x) STRINGIZE2(x) 20 + #define STRINGIZE2(x) #x 21 + #define LINE_STRING STRINGIZE(__LINE__) 22 + 23 + namespace digilent { 24 + 25 + enum class Resolution 26 + { 27 + R1920_1080_60_PP = 0, 28 + R1280_720_60_PP, 29 + R640_480_60_NN 30 + }; 31 + 32 + typedef struct 33 + { 34 + enum Polarity {NEG=0, POS=1}; 35 + Resolution res; 36 + uint16_t h_active, h_fp, h_sync, h_bp; 37 + Polarity h_pol; 38 + uint16_t v_active, v_fp, v_sync, v_bp; 39 + Polarity v_pol; 40 + uint32_t pclk_freq_Hz; 41 + 42 + } timing_t; 43 + 44 + timing_t const timing[] = 45 + { 46 + {Resolution::R1920_1080_60_PP, 1920, 88, 44, 148, timing_t::POS, 1080, 4, 5, 36, timing_t::POS, 148500000}, 47 + {Resolution::R1280_720_60_PP, 1280, 110, 40, 220, timing_t::POS, 720, 5, 5, 20, timing_t::POS, 74250000}, 48 + {Resolution::R640_480_60_NN, 640, 16, 96, 48, timing_t::NEG, 480, 10, 2, 33, timing_t::NEG, 25000000} 49 + }; 50 + 51 + class VideoOutput 52 + { 53 + public: 54 + VideoOutput(u32 VTC_dev_id, u32 clkwiz_dev_id) 55 + { 56 + XVtc_Config *psVtcConfig; 57 + XStatus Status; 58 + 59 + psVtcConfig = XVtc_LookupConfig(VTC_dev_id); 60 + if (NULL == psVtcConfig) { 61 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 62 + } 63 + 64 + Status = XVtc_CfgInitialize( 65 + &sVtc_, 66 + psVtcConfig, 67 + psVtcConfig->BaseAddress 68 + ); 69 + if (Status != XST_SUCCESS) { 70 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 71 + } 72 + 73 + XClk_Wiz_Config *psClkWizConfig; 74 + psClkWizConfig = XClk_Wiz_LookupConfig(clkwiz_dev_id); 75 + if (NULL == psClkWizConfig) { 76 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 77 + } 78 + 79 + Status = XClk_Wiz_CfgInitialize( 80 + &sClkWiz_, 81 + psClkWizConfig, 82 + psClkWizConfig->BaseAddr 83 + ); 84 + if (Status != XST_SUCCESS) { 85 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 86 + } 87 + //Reset clock to hardware default 88 + XClk_Wiz_WriteReg( 89 + sClkWiz_.Config.BaseAddr, 90 + 0x0, 91 + 0x0000000A 92 + ); 93 + //Wait for lock because we will need it later for initializing other IP 94 + while (!(XClk_Wiz_ReadReg(sClkWiz_.Config.BaseAddr, 0x4) & 0x1)); 95 + } 96 + 97 + void reset() 98 + { 99 + XVtc_Reset(&sVtc_); 100 + } 101 + 102 + void configure(Resolution res) 103 + { 104 + size_t i; 105 + for (i = 0; i < sizeof(timing)/sizeof(timing[0]); i++) 106 + { 107 + if (timing[i].res == res) break; 108 + } 109 + 110 + //Configure video clock generator first, since losing clock will reset all IP connected to it 111 + u32 divclk = 8; 112 + double mul = 33.0, clkout_div0 = 33.0; 113 + switch (timing[i].pclk_freq_Hz) 114 + { 115 + case 148500000: 116 + //Factors for 742.5 MHz 117 + mul = 37.125; divclk = 5; clkout_div0 = 1.0; 118 + break; 119 + case 74250000: 120 + //Factors for 371.25 MHz 121 + mul = 37.125; divclk = 4; clkout_div0 = 2.5; 122 + break; 123 + case 25000000: 124 + //Factors for 125 MHz 125 + mul = 10.0; divclk = 1; clkout_div0 = 8.0; 126 + break; 127 + } 128 + //one byte limit for integer part 129 + Xil_AssertVoid(mul < 256.0); 130 + uint16_t mul_frac = (uint16_t)((mul-(uint8_t)mul)*1000); 131 + uint8_t mul_int = (uint8_t)mul; 132 + //MMCME2 limit 133 + Xil_AssertVoid(mul_frac <= 875); 134 + XClk_Wiz_WriteReg( 135 + sClkWiz_.Config.BaseAddr, 136 + 0x200, 137 + ((mul_frac & 0x3FF) << 16) | ((mul_int & 0xFF) << 8) | (divclk & 0xFF) 138 + ); 139 + //one byte limit for integer part 140 + Xil_AssertVoid(clkout_div0 < 256.0); 141 + uint16_t clkout_div0_frac = (uint16_t)((clkout_div0-(uint8_t)clkout_div0)*1000); 142 + uint8_t clkout_div0_int = (uint8_t)clkout_div0; 143 + XClk_Wiz_WriteReg( 144 + sClkWiz_.Config.BaseAddr, 145 + 0x208, 146 + ((clkout_div0_frac & 0x3FF) << 8)| (clkout_div0_int & 0xFF) 147 + ); 148 + //Load configuration 149 + XClk_Wiz_WriteReg( 150 + sClkWiz_.Config.BaseAddr, 151 + 0x25C, 152 + 0x00000003 153 + ); 154 + //Wait for lock 155 + while (!(XClk_Wiz_ReadReg(sClkWiz_.Config.BaseAddr, 0x4) & 0x1)); 156 + 157 + if (i < sizeof(timing)/sizeof(timing[0])) 158 + { 159 + //Will init to 0 (C99 6.7.8.21) 160 + XVtc_Timing sTiming = {}; 161 + sTiming.HActiveVideo = timing[i].h_active; 162 + sTiming.HFrontPorch = timing[i].h_fp; 163 + sTiming.HBackPorch = timing[i].h_bp; 164 + sTiming.HSyncWidth = timing[i].h_sync; 165 + sTiming.HSyncPolarity = (u16)timing[i].h_pol; 166 + sTiming.VActiveVideo = timing[i].v_active; 167 + sTiming.V0FrontPorch = timing[i].v_fp; 168 + sTiming.V0BackPorch = timing[i].v_bp; 169 + sTiming.V0SyncWidth = timing[i].v_sync; 170 + sTiming.VSyncPolarity = (u16)timing[i].v_pol; 171 + XVtc_SetGeneratorTiming(&sVtc_, &sTiming); 172 + XVtc_RegUpdateEnable(&sVtc_); 173 + } 174 + } 175 + 176 + void enable() 177 + { 178 + XVtc_EnableGenerator(&sVtc_); 179 + } 180 + 181 + ~VideoOutput() = default; 182 + 183 + private: 184 + XVtc sVtc_; 185 + XClk_Wiz sClkWiz_; 186 + }; 187 + 188 + } /* namespace digilent */ 189 + 190 + #endif /* VIDEOSOURCE_H_ */
+288
sw/src/Zybo-Z7-20-pcam-5c/src/lscript.ld
··· 1 + /*******************************************************************/ 2 + /* */ 3 + /* This file is automatically generated by linker script generator.*/ 4 + /* */ 5 + /* Version: */ 6 + /* */ 7 + /* Copyright (c) 2010-2016 Xilinx, Inc. All rights reserved. */ 8 + /* */ 9 + /* Description : Cortex-A9 Linker Script */ 10 + /* */ 11 + /*******************************************************************/ 12 + 13 + _STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000; 14 + _HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x2000; 15 + 16 + _ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024; 17 + _SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048; 18 + _IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024; 19 + _FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024; 20 + _UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024; 21 + 22 + /* Define Memories in the system */ 23 + 24 + MEMORY 25 + { 26 + ps7_ddr_0_S_AXI_BASEADDR : ORIGIN = 0x100000, LENGTH = 0x09F00000 27 + ps7_qspi_linear_0_S_AXI_BASEADDR : ORIGIN = 0xFC000000, LENGTH = 0x1000000 28 + ps7_ram_0_S_AXI_BASEADDR : ORIGIN = 0x0, LENGTH = 0x30000 29 + ps7_ram_1_S_AXI_BASEADDR : ORIGIN = 0xFFFF0000, LENGTH = 0xFE00 30 + } 31 + 32 + /* Specify the default entry point to the program */ 33 + 34 + ENTRY(_vector_table) 35 + 36 + /* Define the sections, and where they are mapped in memory */ 37 + 38 + SECTIONS 39 + { 40 + .text : { 41 + KEEP (*(.vectors)) 42 + *(.boot) 43 + *(.text) 44 + *(.text.*) 45 + *(.gnu.linkonce.t.*) 46 + *(.plt) 47 + *(.gnu_warning) 48 + *(.gcc_execpt_table) 49 + *(.glue_7) 50 + *(.glue_7t) 51 + *(.vfp11_veneer) 52 + *(.ARM.extab) 53 + *(.gnu.linkonce.armextab.*) 54 + } > ps7_ddr_0_S_AXI_BASEADDR 55 + 56 + .init : { 57 + KEEP (*(.init)) 58 + } > ps7_ddr_0_S_AXI_BASEADDR 59 + 60 + .fini : { 61 + KEEP (*(.fini)) 62 + } > ps7_ddr_0_S_AXI_BASEADDR 63 + 64 + .rodata : { 65 + __rodata_start = .; 66 + *(.rodata) 67 + *(.rodata.*) 68 + *(.gnu.linkonce.r.*) 69 + __rodata_end = .; 70 + } > ps7_ddr_0_S_AXI_BASEADDR 71 + 72 + .rodata1 : { 73 + __rodata1_start = .; 74 + *(.rodata1) 75 + *(.rodata1.*) 76 + __rodata1_end = .; 77 + } > ps7_ddr_0_S_AXI_BASEADDR 78 + 79 + .sdata2 : { 80 + __sdata2_start = .; 81 + *(.sdata2) 82 + *(.sdata2.*) 83 + *(.gnu.linkonce.s2.*) 84 + __sdata2_end = .; 85 + } > ps7_ddr_0_S_AXI_BASEADDR 86 + 87 + .sbss2 : { 88 + __sbss2_start = .; 89 + *(.sbss2) 90 + *(.sbss2.*) 91 + *(.gnu.linkonce.sb2.*) 92 + __sbss2_end = .; 93 + } > ps7_ddr_0_S_AXI_BASEADDR 94 + 95 + .data : { 96 + __data_start = .; 97 + *(.data) 98 + *(.data.*) 99 + *(.gnu.linkonce.d.*) 100 + *(.jcr) 101 + *(.got) 102 + *(.got.plt) 103 + __data_end = .; 104 + } > ps7_ddr_0_S_AXI_BASEADDR 105 + 106 + .data1 : { 107 + __data1_start = .; 108 + *(.data1) 109 + *(.data1.*) 110 + __data1_end = .; 111 + } > ps7_ddr_0_S_AXI_BASEADDR 112 + 113 + .got : { 114 + *(.got) 115 + } > ps7_ddr_0_S_AXI_BASEADDR 116 + 117 + .ctors : { 118 + __CTOR_LIST__ = .; 119 + ___CTORS_LIST___ = .; 120 + KEEP (*crtbegin.o(.ctors)) 121 + KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors)) 122 + KEEP (*(SORT(.ctors.*))) 123 + KEEP (*(.ctors)) 124 + __CTOR_END__ = .; 125 + ___CTORS_END___ = .; 126 + } > ps7_ddr_0_S_AXI_BASEADDR 127 + 128 + .dtors : { 129 + __DTOR_LIST__ = .; 130 + ___DTORS_LIST___ = .; 131 + KEEP (*crtbegin.o(.dtors)) 132 + KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors)) 133 + KEEP (*(SORT(.dtors.*))) 134 + KEEP (*(.dtors)) 135 + __DTOR_END__ = .; 136 + ___DTORS_END___ = .; 137 + } > ps7_ddr_0_S_AXI_BASEADDR 138 + 139 + .fixup : { 140 + __fixup_start = .; 141 + *(.fixup) 142 + __fixup_end = .; 143 + } > ps7_ddr_0_S_AXI_BASEADDR 144 + 145 + .eh_frame : { 146 + *(.eh_frame) 147 + } > ps7_ddr_0_S_AXI_BASEADDR 148 + 149 + .eh_framehdr : { 150 + __eh_framehdr_start = .; 151 + *(.eh_framehdr) 152 + __eh_framehdr_end = .; 153 + } > ps7_ddr_0_S_AXI_BASEADDR 154 + 155 + .gcc_except_table : { 156 + *(.gcc_except_table) 157 + } > ps7_ddr_0_S_AXI_BASEADDR 158 + 159 + .mmu_tbl (ALIGN(16384)) : { 160 + __mmu_tbl_start = .; 161 + *(.mmu_tbl) 162 + __mmu_tbl_end = .; 163 + } > ps7_ddr_0_S_AXI_BASEADDR 164 + 165 + .ARM.exidx : { 166 + __exidx_start = .; 167 + *(.ARM.exidx*) 168 + *(.gnu.linkonce.armexidix.*.*) 169 + __exidx_end = .; 170 + } > ps7_ddr_0_S_AXI_BASEADDR 171 + 172 + .preinit_array : { 173 + __preinit_array_start = .; 174 + KEEP (*(SORT(.preinit_array.*))) 175 + KEEP (*(.preinit_array)) 176 + __preinit_array_end = .; 177 + } > ps7_ddr_0_S_AXI_BASEADDR 178 + 179 + .init_array : { 180 + __init_array_start = .; 181 + KEEP (*(SORT(.init_array.*))) 182 + KEEP (*(.init_array)) 183 + __init_array_end = .; 184 + } > ps7_ddr_0_S_AXI_BASEADDR 185 + 186 + .fini_array : { 187 + __fini_array_start = .; 188 + KEEP (*(SORT(.fini_array.*))) 189 + KEEP (*(.fini_array)) 190 + __fini_array_end = .; 191 + } > ps7_ddr_0_S_AXI_BASEADDR 192 + 193 + .ARM.attributes : { 194 + __ARM.attributes_start = .; 195 + *(.ARM.attributes) 196 + __ARM.attributes_end = .; 197 + } > ps7_ddr_0_S_AXI_BASEADDR 198 + 199 + .sdata : { 200 + __sdata_start = .; 201 + *(.sdata) 202 + *(.sdata.*) 203 + *(.gnu.linkonce.s.*) 204 + __sdata_end = .; 205 + } > ps7_ddr_0_S_AXI_BASEADDR 206 + 207 + .sbss (NOLOAD) : { 208 + __sbss_start = .; 209 + *(.sbss) 210 + *(.sbss.*) 211 + *(.gnu.linkonce.sb.*) 212 + __sbss_end = .; 213 + } > ps7_ddr_0_S_AXI_BASEADDR 214 + 215 + .tdata : { 216 + __tdata_start = .; 217 + *(.tdata) 218 + *(.tdata.*) 219 + *(.gnu.linkonce.td.*) 220 + __tdata_end = .; 221 + } > ps7_ddr_0_S_AXI_BASEADDR 222 + 223 + .tbss : { 224 + __tbss_start = .; 225 + *(.tbss) 226 + *(.tbss.*) 227 + *(.gnu.linkonce.tb.*) 228 + __tbss_end = .; 229 + } > ps7_ddr_0_S_AXI_BASEADDR 230 + 231 + .bss (NOLOAD) : { 232 + __bss_start = .; 233 + *(.bss) 234 + *(.bss.*) 235 + *(.gnu.linkonce.b.*) 236 + *(COMMON) 237 + __bss_end = .; 238 + } > ps7_ddr_0_S_AXI_BASEADDR 239 + 240 + _SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 ); 241 + 242 + _SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 ); 243 + 244 + /* Generate Stack and Heap definitions */ 245 + 246 + .heap (NOLOAD) : { 247 + . = ALIGN(16); 248 + _heap = .; 249 + HeapBase = .; 250 + _heap_start = .; 251 + . += _HEAP_SIZE; 252 + _heap_end = .; 253 + HeapLimit = .; 254 + } > ps7_ddr_0_S_AXI_BASEADDR 255 + 256 + .stack (NOLOAD) : { 257 + . = ALIGN(16); 258 + _stack_end = .; 259 + . += _STACK_SIZE; 260 + . = ALIGN(16); 261 + _stack = .; 262 + __stack = _stack; 263 + . = ALIGN(16); 264 + _irq_stack_end = .; 265 + . += _IRQ_STACK_SIZE; 266 + . = ALIGN(16); 267 + __irq_stack = .; 268 + _supervisor_stack_end = .; 269 + . += _SUPERVISOR_STACK_SIZE; 270 + . = ALIGN(16); 271 + __supervisor_stack = .; 272 + _abort_stack_end = .; 273 + . += _ABORT_STACK_SIZE; 274 + . = ALIGN(16); 275 + __abort_stack = .; 276 + _fiq_stack_end = .; 277 + . += _FIQ_STACK_SIZE; 278 + . = ALIGN(16); 279 + __fiq_stack = .; 280 + _undef_stack_end = .; 281 + . += _UNDEF_STACK_SIZE; 282 + . = ALIGN(16); 283 + __undef_stack = .; 284 + } > ps7_ddr_0_S_AXI_BASEADDR 285 + 286 + _end = .; 287 + } 288 +
+516
sw/src/Zybo-Z7-20-pcam-5c/src/main.cc
··· 1 + #include "xparameters.h" 2 + //#include "xparameters_ps.h" // for INTRs 3 + 4 + #include "platform.h" 5 + #include "ov5640/OV5640.h" 6 + #include "ov5640/ScuGicInterruptController.h" 7 + #include "ov5640/PS_GPIO.h" 8 + #include "ov5640/AXI_VDMA.h" 9 + #include "ov5640/PS_IIC.h" 10 + 11 + #include "MIPI_D_PHY_RX.h" 12 + #include "MIPI_CSI_2_RX.h" 13 + #include "xuartps.h" 14 + 15 + #include <cstdint> 16 + #include <xil_io.h> 17 + #include <xil_types.h> 18 + 19 + #define IRPT_CTL_DEVID XPAR_XSCUGIC_0_BASEADDR 20 + #define GPIO_DEVID XPAR_GPIO0_BASEADDR 21 + #define GPIO_IRPT_ID XPAR_PS7_GPIO_0_INTR 22 + #define CAM_I2C_DEVID XPAR_I2C0_BASEADDR 23 + #define CAM_I2C_IRPT_ID XPAR_PS7_I2C_0_INTR 24 + #define VDMA_DEVID XPAR_AXI_VDMA_0_BASEADDR 25 + #define VDMA_MM2S_IRPT_ID XPAR_FABRIC_AXI_VDMA_0_INTR 26 + #define VDMA_S2MM_IRPT_ID XPAR_FABRIC_AXI_VDMA_0_INTR_1 27 + #define CAM_I2C_SCLK_RATE 100000 28 + 29 + #define DDR_BASE_ADDR XPAR_DDR_MEM_BASEADDR 30 + #define MEM_BASE_ADDR (DDR_BASE_ADDR + 0x0A000000) 31 + 32 + #define GAMMA_BASE_ADDR XPAR_AXI_GAMMACORRECTION_0_BASEADDR 33 + 34 + #define DEBUG_EN 0x0 35 + #define UART_BASEADDR XPS_UART0_BASEADDR 36 + 37 + using namespace digilent; 38 + 39 + void dFlushUart(); 40 + uint8_t dGetChar(); 41 + void pipeline_mode_change(AXI_VDMA<ScuGicInterruptController>& vdma_driver, 42 + OV5640& cam, 43 + VideoOutput& vid, 44 + Resolution res, 45 + OV5640_cfg::mode_t mode 46 + ); 47 + 48 + int main() 49 + { 50 + //init_platform(); 51 + //Xil_ICacheEnable(); 52 + //Xil_DCacheEnable(); 53 + 54 + ScuGicInterruptController irpt_ctl( 55 + IRPT_CTL_DEVID 56 + ); 57 + PS_GPIO<ScuGicInterruptController> gpio_driver( 58 + GPIO_DEVID, 59 + irpt_ctl, 60 + GPIO_IRPT_ID 61 + ); 62 + PS_IIC<ScuGicInterruptController> iic_driver( 63 + CAM_I2C_DEVID, 64 + irpt_ctl, 65 + CAM_I2C_IRPT_ID, 66 + CAM_I2C_SCLK_RATE 67 + ); 68 + OV5640 cam( 69 + iic_driver, 70 + gpio_driver 71 + ); 72 + AXI_VDMA<ScuGicInterruptController> vdma_driver( 73 + VDMA_DEVID, 74 + MEM_BASE_ADDR, 75 + irpt_ctl, 76 + VDMA_MM2S_IRPT_ID, 77 + VDMA_S2MM_IRPT_ID 78 + ); 79 + VideoOutput vid( 80 + XPAR_VTG_BASEADDR, 81 + XPAR_VIDEO_DYNCLK_BASEADDR 82 + ); 83 + pipeline_mode_change( 84 + vdma_driver, 85 + cam, 86 + vid, 87 + Resolution::R1920_1080_60_PP, 88 + OV5640_cfg::mode_t::MODE_1080P_1920_1080_30fps 89 + ); 90 + xil_printf("Video init done.\r\n"); 91 + 92 + // Liquid lens control 93 + uint8_t read_char0 = 0; 94 + uint8_t read_char1 = 0; 95 + uint8_t read_char2 = 0; 96 + uint8_t read_char4 = 0; 97 + uint8_t read_char5 = 0; 98 + uint16_t reg_addr; 99 + uint8_t reg_value; 100 + 101 + while (1) 102 + { 103 + xil_printf("\r\n\r\n\r\nPcam 5C MAIN OPTIONS\r\n"); 104 + xil_printf("\r\nPlease press the key corresponding to the desired option:"); 105 + xil_printf("\r\n a. Change Resolution"); 106 + xil_printf("\r\n b. Change Liquid Lens Focus"); 107 + xil_printf("\r\n d. Change Image Format (Raw or RGB)"); 108 + xil_printf("\r\n e. Write a Register Inside the Image Sensor"); 109 + xil_printf("\r\n f. Read a Register Inside the Image Sensor"); 110 + xil_printf("\r\n g. Change Gamma Correction Factor Value"); 111 + xil_printf("\r\n h. Change AWB Settings\r\n\r\n"); 112 + 113 + read_char0 = getchar(); getchar(); 114 + xil_printf("Read: %d\r\n", read_char0); 115 + 116 + switch (read_char0) 117 + { 118 + case 'a': 119 + xil_printf("\r\n Please press the key corresponding to the desired resolution:"); 120 + xil_printf("\r\n 1. 1280 x 720, 60fps"); 121 + xil_printf("\r\n 2. 1920 x 1080, 15fps"); 122 + xil_printf("\r\n 3. 1920 x 1080, 30fps"); 123 + 124 + read_char1 = getchar(); getchar(); 125 + xil_printf("\r\nRead: %d", read_char1); 126 + 127 + switch (read_char1) 128 + { 129 + case '1': 130 + pipeline_mode_change( 131 + vdma_driver, 132 + cam, 133 + vid, 134 + Resolution::R1280_720_60_PP, 135 + OV5640_cfg::mode_t::MODE_720P_1280_720_60fps 136 + ); 137 + xil_printf("Resolution change done.\r\n"); 138 + break; 139 + case '2': 140 + pipeline_mode_change( 141 + vdma_driver, 142 + cam, 143 + vid, 144 + Resolution::R1920_1080_60_PP, 145 + OV5640_cfg::mode_t::MODE_1080P_1920_1080_15fps 146 + ); 147 + xil_printf("Resolution change done.\r\n"); 148 + break; 149 + case '3': 150 + pipeline_mode_change( 151 + vdma_driver, 152 + cam, 153 + vid, 154 + Resolution::R1920_1080_60_PP, 155 + OV5640_cfg::mode_t::MODE_1080P_1920_1080_30fps 156 + ); 157 + xil_printf("Resolution change done.\r\n"); 158 + break; 159 + default: 160 + xil_printf("\r\n Selection is outside the available options! Please retry..."); 161 + } 162 + break; 163 + 164 + case 'b': 165 + xil_printf("\r\n\r\nPlease enter value of liquid lens register, in hex, with small letters (2 nibbles): 0x"); 166 + //A, B, C,..., F need to be entered with small letters 167 + while (read_char1 < 48) { 168 + read_char1 = getchar(); 169 + } 170 + while (read_char2 < 48) { 171 + read_char2 = getchar(); getchar(); 172 + } 173 + // If character is a digit, convert from ASCII code to a digit between 0 and 9 174 + if (read_char1 <= 57) { 175 + read_char1 -= 48; 176 + } 177 + // If character is a letter, convert ASCII code to a number between 10 and 15 178 + else { 179 + read_char1 -= 87; 180 + } 181 + // If character is a digit, convert from ASCII code to a digit between 0 and 9 182 + if (read_char2 <= 57) { 183 + read_char2 -= 48; 184 + } 185 + // If character is a letter, convert ASCII code to a number between 10 and 15 186 + else { 187 + read_char2 -= 87; 188 + } 189 + cam.writeRegLiquid((uint8_t) (16*read_char1 + read_char2)); 190 + xil_printf("\r\nWrote to liquid lens controller: %x", (uint8_t) (16*read_char1 + read_char2)); 191 + break; 192 + 193 + case 'd': 194 + xil_printf("\r\n Please press the key corresponding to the desired setting:"); 195 + xil_printf("\r\n 1. Select image format to be RGB, output still Raw"); 196 + xil_printf("\r\n 2. Select image format & output to both be Raw"); 197 + 198 + read_char1 = getchar(); getchar(); 199 + xil_printf("\r\nRead: %d", read_char1); 200 + 201 + switch (read_char1) 202 + { 203 + case '1': 204 + cam.set_isp_format(OV5640_cfg::isp_format_t::ISP_RGB); 205 + xil_printf("Settings change done.\r\n"); 206 + break; 207 + case '2': 208 + cam.set_isp_format(OV5640_cfg::isp_format_t::ISP_RAW); 209 + xil_printf("Settings change done.\r\n"); 210 + break; 211 + default: 212 + xil_printf("\r\n Selection is outside the available options! Please retry..."); 213 + } 214 + break; 215 + 216 + case 'e': 217 + xil_printf("\r\nPlease enter address of image sensor register, in hex, with small letters (4 nibbles): \r\n"); 218 + //A, B, C,..., F need to be entered with small letters 219 + while (read_char1 < 48) { 220 + read_char1 = getchar(); 221 + } 222 + while (read_char2 < 48) { 223 + read_char2 = getchar(); 224 + } 225 + while (read_char4 < 48) { 226 + read_char4 = getchar(); 227 + } 228 + while (read_char5 < 48) { 229 + read_char5 = getchar(); getchar(); 230 + } 231 + // If character is a digit, convert from ASCII code to a digit between 0 and 9 232 + if (read_char1 <= 57) { 233 + read_char1 -= 48; 234 + } 235 + // If character is a letter, convert ASCII code to a number between 10 and 15 236 + else { 237 + read_char1 -= 87; 238 + } 239 + // If character is a digit, convert from ASCII code to a digit between 0 and 9 240 + if (read_char2 <= 57) { 241 + read_char2 -= 48; 242 + } 243 + // If character is a letter, convert ASCII code to a number between 10 and 15 244 + else { 245 + read_char2 -= 87; 246 + } 247 + // If character is a digit, convert from ASCII code to a digit between 0 and 9 248 + if (read_char4 <= 57) { 249 + read_char4 -= 48; 250 + } 251 + // If character is a letter, convert ASCII code to a number between 10 and 15 252 + else { 253 + read_char4 -= 87; 254 + } 255 + // If character is a digit, convert from ASCII code to a digit between 0 and 9 256 + if (read_char5 <= 57) { 257 + read_char5 -= 48; 258 + } 259 + // If character is a letter, convert ASCII code to a number between 10 and 15 260 + else { 261 + read_char5 -= 87; 262 + } 263 + reg_addr = 16*(16*(16*read_char1 + read_char2)+read_char4)+read_char5; 264 + xil_printf("Desired Register Address: %x\r\n", reg_addr); 265 + 266 + read_char1 = 0; 267 + read_char2 = 0; 268 + xil_printf("\r\nPlease enter value of image sensor register, in hex, with small letters (2 nibbles): \r\n"); 269 + //A, B, C,..., F need to be entered with small letters 270 + while (read_char1 < 48) { 271 + read_char1 = getchar(); 272 + } 273 + while (read_char2 < 48) { 274 + read_char2 = getchar(); getchar(); 275 + } 276 + // If character is a digit, convert from ASCII code to a digit between 0 and 9 277 + if (read_char1 <= 57) { 278 + read_char1 -= 48; 279 + } 280 + // If character is a letter, convert ASCII code to a number between 10 and 15 281 + else { 282 + read_char1 -= 87; 283 + } 284 + // If character is a digit, convert from ASCII code to a digit between 0 and 9 285 + if (read_char2 <= 57) { 286 + read_char2 -= 48; 287 + } 288 + // If character is a letter, convert ASCII code to a number between 10 and 15 289 + else { 290 + read_char2 -= 87; 291 + } 292 + reg_value = 16*read_char1 + read_char2; 293 + xil_printf("Desired Register Value: %x\r\n", reg_value); 294 + cam.writeReg(reg_addr, reg_value); 295 + xil_printf("Register write done.\r\n"); 296 + 297 + break; 298 + 299 + case 'f': 300 + xil_printf("Please enter address of image sensor register, in hex, with small letters (4 nibbles): \r\n"); 301 + //A, B, C,..., F need to be entered with small letters 302 + while (read_char1 < 48) { 303 + read_char1 = getchar(); 304 + } 305 + while (read_char2 < 48) { 306 + read_char2 = getchar(); 307 + } 308 + while (read_char4 < 48) { 309 + read_char4 = getchar(); 310 + } 311 + while (read_char5 < 48) { 312 + read_char5 = getchar(); getchar(); 313 + } 314 + // If character is a digit, convert from ASCII code to a digit between 0 and 9 315 + if (read_char1 <= 57) { 316 + read_char1 -= 48; 317 + } 318 + // If character is a letter, convert ASCII code to a number between 10 and 15 319 + else { 320 + read_char1 -= 87; 321 + } 322 + // If character is a digit, convert from ASCII code to a digit between 0 and 9 323 + if (read_char2 <= 57) { 324 + read_char2 -= 48; 325 + } 326 + // If character is a letter, convert ASCII code to a number between 10 and 15 327 + else { 328 + read_char2 -= 87; 329 + } 330 + // If character is a digit, convert from ASCII code to a digit between 0 and 9 331 + if (read_char4 <= 57) { 332 + read_char4 -= 48; 333 + } 334 + // If character is a letter, convert ASCII code to a number between 10 and 15 335 + else { 336 + read_char4 -= 87; 337 + } 338 + // If character is a digit, convert from ASCII code to a digit between 0 and 9 339 + if (read_char5 <= 57) { 340 + read_char5 -= 48; 341 + } 342 + // If character is a letter, convert ASCII code to a number between 10 and 15 343 + else { 344 + read_char5 -= 87; 345 + } 346 + reg_addr = 16*(16*(16*read_char1 + read_char2)+read_char4)+read_char5; 347 + xil_printf("Desired Register Address: %x\r\n", reg_addr); 348 + 349 + cam.readReg(reg_addr, reg_value); 350 + xil_printf("Value of Desired Register: %x\r\n", reg_value); 351 + break; 352 + 353 + case 'g': 354 + xil_printf(" Please press the key corresponding to the desired Gamma factor:\r\n"); 355 + xil_printf(" 1. Gamma Factor = 1\r\n"); 356 + xil_printf(" 2. Gamma Factor = 1/1.2\r\n"); 357 + xil_printf(" 3. Gamma Factor = 1/1.5\r\n"); 358 + xil_printf(" 4. Gamma Factor = 1/1.8\r\n"); 359 + xil_printf(" 5. Gamma Factor = 1/2.2\r\n"); 360 + 361 + read_char1 = getchar(); getchar(); 362 + 363 + xil_printf("Read: %d\r\n", read_char1); 364 + // Convert from ASCII to numeric 365 + read_char1 = read_char1 - 48; 366 + if ((read_char1 > 0) && (read_char1 < 6)) { 367 + Xil_Out32(GAMMA_BASE_ADDR, read_char1-1); 368 + xil_printf("Gamma value changed to option %d.\r\n", read_char1); 369 + } 370 + else { 371 + xil_printf(" Selection is outside the available options! Please retry...\r\n"); 372 + } 373 + break; 374 + 375 + case 'h': 376 + xil_printf(" Please press the key corresponding to the desired AWB change:\r\n"); 377 + xil_printf(" 1. Enable Advanced AWB\r\n"); 378 + xil_printf(" 2. Enable Simple AWB\r\n"); 379 + xil_printf(" 3. Disable AWB\r\n"); 380 + 381 + read_char1 = getchar(); getchar(); 382 + 383 + xil_printf("Read: %d\r\n", read_char1); 384 + 385 + switch (read_char1) 386 + { 387 + case '1': 388 + cam.set_awb(OV5640_cfg::awb_t::AWB_ADVANCED); 389 + xil_printf("Enabled Advanced AWB\r\n"); 390 + break; 391 + case '2': 392 + cam.set_awb(OV5640_cfg::awb_t::AWB_SIMPLE); 393 + xil_printf("Enabled Simple AWB\r\n"); 394 + break; 395 + case '3': 396 + cam.set_awb(OV5640_cfg::awb_t::AWB_DISABLED); 397 + xil_printf("Disabled AWB\r\n"); 398 + break; 399 + default: 400 + xil_printf(" Selection is outside the available options! Please retry...\r\n"); 401 + } 402 + break; 403 + 404 + default: 405 + xil_printf(" Selection is outside the available options! Please retry...\r\n"); 406 + } 407 + 408 + read_char1 = 0; 409 + read_char2 = 0; 410 + read_char4 = 0; 411 + read_char5 = 0; 412 + } 413 + 414 + //cleanup_platform(); 415 + //Xil_ICacheDisable(); 416 + //Xil_DCacheDisable(); 417 + 418 + return 0; 419 + } 420 + 421 + void dFlushUart() 422 + { 423 + while (XUartPs_IsReceiveData(UART_BASEADDR)) 424 + XUartPs_ReadReg(UART_BASEADDR, XUARTPS_FIFO_OFFSET); 425 + } 426 + 427 + uint8_t dGetChar() 428 + { 429 + uint8_t chRxCh = '0'; 430 + //dFlushUart(); 431 + /* Wait for data on UART */ 432 + while (XUartPs_IsReceiveData(UART_BASEADDR)) 433 + { 434 + chRxCh = XUartPs_ReadReg(UART_BASEADDR, XUARTPS_FIFO_OFFSET); 435 + if (chRxCh == '\n') 436 + { 437 + break; 438 + } 439 + } 440 + return chRxCh; 441 + } 442 + 443 + void pipeline_mode_change(AXI_VDMA<ScuGicInterruptController>& vdma_driver, 444 + OV5640& cam, 445 + VideoOutput& vid, 446 + Resolution res, 447 + OV5640_cfg::mode_t mode 448 + ) 449 + { 450 + // Bring up input pipeline back-to-front 451 + vdma_driver.resetWrite(); 452 + MIPI_CSI_2_RX_mWriteReg( 453 + XPAR_MIPI_CSI_2_RX_0_BASEADDR, 454 + CR_OFFSET, 455 + (CR_RESET_MASK & ~CR_ENABLE_MASK) 456 + ); 457 + MIPI_D_PHY_RX_mWriteReg( 458 + XPAR_MIPI_D_PHY_RX_0_BASEADDR, 459 + CR_OFFSET, 460 + (CR_RESET_MASK & ~CR_ENABLE_MASK) 461 + ); 462 + #if (DEBUG_EN == 0x0) 463 + cam.reset(); 464 + #endif 465 + vdma_driver.configureWrite( 466 + timing[static_cast<int>(res)].h_active, 467 + timing[static_cast<int>(res)].v_active 468 + ); 469 + // Set Gamma correction factor to 1/1.8 470 + Xil_Out32(GAMMA_BASE_ADDR, 3); 471 + // TODO CSI-2, D-PHY config here 472 + #if (DEBUG_EN == 0x0) 473 + cam.init(); 474 + vdma_driver.enableWrite(); 475 + #endif 476 + MIPI_CSI_2_RX_mWriteReg( 477 + XPAR_MIPI_CSI_2_RX_0_BASEADDR, 478 + CR_OFFSET, 479 + CR_ENABLE_MASK 480 + ); 481 + MIPI_D_PHY_RX_mWriteReg( 482 + XPAR_MIPI_D_PHY_RX_0_BASEADDR, 483 + CR_OFFSET, 484 + CR_ENABLE_MASK 485 + ); 486 + #if (DEBUG_EN == 0x0) 487 + cam.set_mode(mode); 488 + cam.set_awb(OV5640_cfg::awb_t::AWB_ADVANCED); 489 + #endif 490 + // Bring up output pipeline back-to-front 491 + vid.reset(); 492 + vdma_driver.resetRead(); 493 + vid.configure(res); 494 + // Alloc mem for frames 495 + vdma_driver.configureRead( 496 + timing[static_cast<int>(res)].h_active, 497 + timing[static_cast<int>(res)].v_active 498 + ); 499 + #if (DEBUG_EN == 0x1) 500 + // Write RBG set to test pipeline 501 + // ... 502 + // VDMA Frame 0 Addr: 0x0A000000 503 + // VDMA Frame 1 Addr: 0x0A5EEC00 504 + // VDMA Frame 2 Addr: 0x0ABDD800 505 + u32 framesAddr[3] = {0x0A000000, 0x0A5EEC00, 0x0ABDD800}; 506 + // difference : 5E EC00 507 + u32 diffAddrs = framesAddr[1] - framesAddr[0]; 508 + for (u32 x = 0; x < diffAddrs; x++) { 509 + Xil_Out32(framesAddr[0] + x, 0x00FFFFFF); 510 + Xil_Out32(framesAddr[1] + x, 0x00FFFFFF); 511 + Xil_Out32(framesAddr[2] + x, 0x00FFFFFF); 512 + } 513 + #endif 514 + vid.enable(); 515 + vdma_driver.enableRead(); 516 + }
+393
sw/src/Zybo-Z7-20-pcam-5c/src/ov5640/AXI_VDMA.h
··· 1 + /* 2 + * AXI_VDMA.h 3 + * 4 + * Created on: Sep 2, 2016 5 + * Author: Elod 6 + */ 7 + 8 + #ifndef AXI_VDMA_H_ 9 + #define AXI_VDMA_H_ 10 + 11 + #include <cstdint> 12 + #include <cstdlib> 13 + #include <stdexcept> 14 + #include <functional> 15 + #include <iostream> 16 + #include <xil_types.h> 17 + 18 + #include "xaxivdma.h" 19 + 20 + #define STRINGIZE(x) STRINGIZE2(x) 21 + #define STRINGIZE2(x) #x 22 + #define LINE_STRING STRINGIZE(__LINE__) 23 + 24 + namespace digilent 25 + { 26 + 27 + /*! 28 + * \brief Driver class for Xilinx AXI VDMA IP. Needs to have stable clocks before 29 + * instantiation to be able to complete hardware reset. 30 + */ 31 + template <typename IrptCtl> 32 + class AXI_VDMA 33 + { 34 + typedef struct { 35 + /* The state variable to keep track if the initialization is done */ 36 + unsigned int init_done; 37 + /* The XAxiVdma_DmaSetup structure contains all the necessary information to 38 + * start a frame write or read. */ 39 + XAxiVdma_DmaSetup ReadCfg; 40 + XAxiVdma_DmaSetup WriteCfg; 41 + /* Horizontal size of frame */ 42 + unsigned int hsize; 43 + /* Vertical size of frame */ 44 + unsigned int vsize; 45 + /* Buffer address from where read and write will be done by VDMA */ 46 + unsigned int buffer_address; 47 + /* Flag to tell VDMA to interrupt on frame completion */ 48 + unsigned int enable_frm_cnt_intr; 49 + /* The counter to tell VDMA on how many frames the interrupt should happen */ 50 + unsigned int number_of_frame_count; 51 + } vdma_context_t; 52 + public: 53 + // Utility function to extract function object from CallbackRef and call it. 54 + // This should call our member function handlers below. 55 + template <typename Func> 56 + static void MyCallback(void* CallbackRef, uint32_t mask_or_type) 57 + { 58 + auto pfn = static_cast<Func*>(CallbackRef); 59 + pfn->operator()(mask_or_type); 60 + } 61 + 62 + AXI_VDMA(uint32_t dev_id, 63 + UINTPTR frame_buf_base_addr, 64 + IrptCtl& irpt_ctl, 65 + uint32_t rd_irpt_id, 66 + uint32_t wr_irpt_id 67 + ) : 68 + rd_handler_(std::bind(&AXI_VDMA::readHandler, this, std::placeholders::_1)), 69 + wr_handler_(std::bind(&AXI_VDMA::writeHandler, this, std::placeholders::_1)), 70 + rd_err_handler_(std::bind(&AXI_VDMA::readErrorHandler, this, std::placeholders::_1)), 71 + wr_err_handler_(std::bind(&AXI_VDMA::writeErrorHandler, this, std::placeholders::_1)), 72 + context_{}, 73 + frame_buf_base_addr_(frame_buf_base_addr), 74 + irpt_ctl_(irpt_ctl), 75 + prevHVSize({0, 0}) 76 + { 77 + XAxiVdma_Config* psConf; 78 + XStatus Status; 79 + 80 + psConf = XAxiVdma_LookupConfig(dev_id); 81 + 82 + if (!psConf) 83 + { 84 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 85 + } 86 + 87 + //Initialize driver instance and reset VDMA 88 + Status = XAxiVdma_CfgInitialize( 89 + &drv_inst_, 90 + psConf, 91 + psConf->BaseAddress 92 + ); 93 + 94 + if (Status != XST_SUCCESS) 95 + { 96 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 97 + } 98 + 99 + //Set error interrupt error handlers, which for some reason need completion handler defined too 100 + XAxiVdma_SetCallBack( 101 + &drv_inst_, 102 + XAXIVDMA_HANDLER_GENERAL, 103 + reinterpret_cast<void*>(&MyCallback<decltype(rd_handler_)>), 104 + &rd_handler_, 105 + XAXIVDMA_READ 106 + ); 107 + XAxiVdma_SetCallBack( 108 + &drv_inst_, 109 + XAXIVDMA_HANDLER_GENERAL, 110 + reinterpret_cast<void*>(&MyCallback<decltype(wr_handler_)>), 111 + &wr_handler_, 112 + XAXIVDMA_WRITE 113 + ); 114 + XAxiVdma_SetCallBack( 115 + &drv_inst_, 116 + XAXIVDMA_HANDLER_ERROR, 117 + reinterpret_cast<void*>(&MyCallback<decltype(rd_err_handler_)>), 118 + &rd_err_handler_, 119 + XAXIVDMA_READ 120 + ); 121 + XAxiVdma_SetCallBack( 122 + &drv_inst_, 123 + XAXIVDMA_HANDLER_ERROR, 124 + reinterpret_cast<void*>(&MyCallback<decltype(wr_err_handler_)>), 125 + &wr_err_handler_, 126 + XAXIVDMA_WRITE 127 + ); 128 + 129 + //Register the IIC handler with the interrupt controller 130 + irpt_ctl_.registerHandler(rd_irpt_id, &XAxiVdma_ReadIntrHandler, &drv_inst_); 131 + irpt_ctl_.enableInterrupt(rd_irpt_id); 132 + irpt_ctl_.registerHandler(wr_irpt_id, &XAxiVdma_WriteIntrHandler, &drv_inst_); 133 + irpt_ctl_.enableInterrupt(wr_irpt_id); 134 + irpt_ctl_.enableInterrupts(); 135 + } 136 + 137 + void resetRead() 138 + { 139 + //XAxiVdma_ChannelStop(&drv_inst_.ReadChannel); 140 + //while (XAxiVdma_ChannelIsRunning(&drv_inst_.ReadChannel)); 141 + 142 + XAxiVdma_ChannelReset(&drv_inst_.ReadChannel); 143 + 144 + int Polls = RESET_POLL; 145 + 146 + while (Polls && XAxiVdma_ChannelResetNotDone(&drv_inst_.ReadChannel)) 147 + { 148 + --Polls; 149 + } 150 + 151 + if (!Polls) 152 + { 153 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 154 + } 155 + } 156 + 157 + void resetWrite() 158 + { 159 + //XAxiVdma_ChannelStop(&drv_inst_.WriteChannel); 160 + //while (XAxiVdma_ChannelIsRunning(&drv_inst_.WriteChannel)); 161 + 162 + XAxiVdma_ChannelReset(&drv_inst_.WriteChannel); 163 + 164 + int Polls = RESET_POLL; 165 + 166 + while (Polls && XAxiVdma_ChannelResetNotDone(&drv_inst_.WriteChannel)) 167 + { 168 + --Polls; 169 + } 170 + 171 + if (!Polls) 172 + { 173 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 174 + } 175 + } 176 + 177 + void configureRead(uint16_t h_res, uint16_t v_res) 178 + { 179 + XStatus status; 180 + 181 + initMemAxiVdma(h_res, v_res); 182 + 183 + // Set again h/v attr 184 + context_.ReadCfg.HoriSizeInput = h_res * drv_inst_.ReadChannel.StreamWidth; 185 + context_.ReadCfg.VertSizeInput = v_res; 186 + context_.ReadCfg.Stride = context_.ReadCfg.HoriSizeInput; 187 + // No delays 188 + context_.ReadCfg.FrameDelay = 0; 189 + context_.ReadCfg.EnableCircularBuf = 1; 190 + context_.ReadCfg.EnableSync = 1; 191 + context_.ReadCfg.PointNum = 0; 192 + context_.ReadCfg.EnableFrameCounter = 0; 193 + // Set it on 0 until we sync 194 + context_.ReadCfg.FixedFrameStoreAddr = 0; 195 + 196 + status = XAxiVdma_DmaConfig( 197 + &drv_inst_, 198 + XAXIVDMA_READ, 199 + &context_.ReadCfg 200 + ); 201 + 202 + if (XST_SUCCESS != status) 203 + { 204 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 205 + } 206 + 207 + status = XAxiVdma_DmaSetBufferAddr( 208 + &drv_inst_, 209 + XAXIVDMA_READ, 210 + context_.ReadCfg.FrameStoreStartAddr 211 + ); 212 + 213 + if (XST_SUCCESS != status) 214 + { 215 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 216 + } 217 + 218 + //Clear errors in SR 219 + XAxiVdma_ClearChannelErrors( 220 + &drv_inst_.ReadChannel, 221 + XAXIVDMA_SR_ERR_ALL_MASK 222 + ); 223 + //Enable read channel error and frame count interrupts 224 + XAxiVdma_IntrEnable( 225 + &drv_inst_, 226 + XAXIVDMA_IXR_ERROR_MASK, 227 + XAXIVDMA_READ 228 + ); 229 + } 230 + 231 + void enableRead() 232 + { 233 + XStatus status; 234 + //Start read channel 235 + status = XAxiVdma_DmaStart( 236 + &drv_inst_, 237 + XAXIVDMA_READ 238 + ); 239 + 240 + if (XST_SUCCESS != status) 241 + { 242 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 243 + } 244 + } 245 + 246 + void configureWrite(uint16_t h_res, uint16_t v_res) 247 + { 248 + XStatus status; 249 + 250 + initMemAxiVdma(h_res, v_res); 251 + 252 + // Set again h/v attr 253 + context_.WriteCfg.HoriSizeInput = h_res * drv_inst_.ReadChannel.StreamWidth; 254 + context_.WriteCfg.VertSizeInput = v_res; 255 + context_.WriteCfg.Stride = context_.WriteCfg.HoriSizeInput; 256 + context_.WriteCfg.FrameDelay = 1; 257 + context_.WriteCfg.EnableCircularBuf = 1; 258 + // Gen-Lock 259 + context_.WriteCfg.EnableSync = 1; 260 + context_.WriteCfg.PointNum = 0; 261 + context_.WriteCfg.EnableFrameCounter = 0; 262 + // Ignored, since we circle through buffers 263 + context_.WriteCfg.FixedFrameStoreAddr = 0; 264 + 265 + status = XAxiVdma_ClearDmaChannelErrors( 266 + &drv_inst_, 267 + XAXIVDMA_WRITE, 268 + XAXIVDMA_SR_ERR_ALL_MASK 269 + ); 270 + status = XAxiVdma_DmaConfig( 271 + &drv_inst_, 272 + XAXIVDMA_WRITE, 273 + &context_.WriteCfg 274 + ); 275 + 276 + if (XST_SUCCESS != status) 277 + { 278 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 279 + } 280 + 281 + status = XAxiVdma_DmaSetBufferAddr( 282 + &drv_inst_, 283 + XAXIVDMA_WRITE, 284 + context_.WriteCfg.FrameStoreStartAddr 285 + ); 286 + 287 + if (XST_SUCCESS != status) 288 + { 289 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 290 + } 291 + //Clear errors in SR 292 + XAxiVdma_ClearChannelErrors( 293 + &drv_inst_.WriteChannel, 294 + XAXIVDMA_SR_ERR_ALL_MASK 295 + ); 296 + //Unmask error interrupts 297 + XAxiVdma_MaskS2MMErrIntr( 298 + &drv_inst_, 299 + ~XAXIVDMA_S2MM_IRQ_ERR_ALL_MASK, 300 + XAXIVDMA_WRITE 301 + ); 302 + //Enable write channel error and frame count interrupts 303 + XAxiVdma_IntrEnable( 304 + &drv_inst_, 305 + XAXIVDMA_IXR_ERROR_MASK, 306 + XAXIVDMA_WRITE 307 + ); 308 + } 309 + 310 + void enableWrite() 311 + { 312 + XStatus status; 313 + //Start read channel 314 + status = XAxiVdma_DmaStart( 315 + &drv_inst_, 316 + XAXIVDMA_WRITE 317 + ); 318 + 319 + if (XST_SUCCESS != status) 320 + { 321 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 322 + } 323 + } 324 + 325 + void readHandler(uint32_t irq_types) 326 + { 327 + std::cout << "VDMA:read complete - " << irq_types << std::endl; 328 + } 329 + 330 + void writeHandler(uint32_t irq_types) 331 + { 332 + std::cout << "VDMA:write complete - " << irq_types << std::endl; 333 + } 334 + 335 + void readErrorHandler(uint32_t mask) 336 + { 337 + std::cout << "VDMA:read error - " << mask << std::endl; 338 + } 339 + 340 + void writeErrorHandler(uint32_t mask) 341 + { 342 + std::cout << "VDMA:write error - " << mask << std::endl; 343 + } 344 + 345 + void initMemAxiVdma(uint16_t hRes, uint16_t vRes) 346 + { 347 + if ((hRes != 0 && vRes != 0) && 348 + (prevHVSize.hRes != hRes && prevHVSize.vRes != vRes) 349 + ) 350 + { 351 + int iFrm = 0; 352 + // ReadCfg or WriteCfg, free even if alloc mem 353 + // has not been done. TODO: avoid freeing before 354 + // alloc mem. 355 + prevHVSize.hRes = hRes; 356 + prevHVSize.vRes = vRes; 357 + // SteamWidth ~ 3 358 + //context_.ReadCfg.HoriSizeInput = prevHVSize.hRes * drv_inst_.ReadChannel.StreamWidth; 359 + //context_.ReadCfg.VertSizeInput = prevHVSize.vRes; 360 + for (iFrm = 0; iFrm < drv_inst_.MaxNumFrames; iFrm++) 361 + { 362 + size_t dimFrame = (prevHVSize.hRes * drv_inst_.ReadChannel.StreamWidth) * prevHVSize.vRes; 363 + // Max nr of bytes set on 0: 5E EC00 ~ 5MB per frame 364 + //memset((void*)frame_buf_base_addr_, 0, dimFrame); 365 + context_.ReadCfg.FrameStoreStartAddr[iFrm] = frame_buf_base_addr_; 366 + context_.WriteCfg.FrameStoreStartAddr[iFrm] = frame_buf_base_addr_; 367 + xil_printf("VDMA Frame %d Addr: 0x%08x\r\n", iFrm, frame_buf_base_addr_); 368 + frame_buf_base_addr_ += dimFrame; 369 + } 370 + } 371 + } 372 + 373 + ~AXI_VDMA() {} 374 + 375 + private: 376 + XAxiVdma drv_inst_; 377 + std::function<void(uint32_t)> rd_handler_; 378 + std::function<void(uint32_t)> wr_handler_; 379 + std::function<void(uint32_t)> rd_err_handler_; 380 + std::function<void(uint32_t)> wr_err_handler_; 381 + vdma_context_t context_; 382 + UINTPTR frame_buf_base_addr_; 383 + IrptCtl& irpt_ctl_; 384 + int const RESET_POLL = 1000; 385 + struct { 386 + uint16_t hRes; 387 + uint16_t vRes; 388 + } prevHVSize; 389 + }; 390 + 391 + } //namespace digilent 392 + 393 + #endif /* AXI_VDMA_H_ */
+24
sw/src/Zybo-Z7-20-pcam-5c/src/ov5640/GPIO_Client.h
··· 1 + /* 2 + * GPIOClient.h 3 + * 4 + * Created on: Jun 7, 2016 5 + * Author: Elod 6 + */ 7 + 8 + #ifndef GPIOCLIENT_H_ 9 + #define GPIOCLIENT_H_ 10 + 11 + namespace digilent { 12 + 13 + class GPIO_Client { 14 + public: 15 + using Bits = enum {CAM_GPIO0}; 16 + virtual void setBit(Bits) = 0; 17 + virtual void clearBit(Bits bits) = 0; 18 + virtual void commit() = 0; 19 + ~GPIO_Client() = default; 20 + }; 21 + 22 + } /* namespace digilent */ 23 + 24 + #endif /* GPIOCLIENT_H_ */
+30
sw/src/Zybo-Z7-20-pcam-5c/src/ov5640/I2C_Client.h
··· 1 + /* 2 + * iicclient.h 3 + * 4 + * Created on: May 26, 2016 5 + * Author: Elod 6 + */ 7 + 8 + #ifndef IICCLIENT_H_ 9 + #define IICCLIENT_H_ 10 + 11 + #include <stdint.h> 12 + #include <stdexcept> 13 + #include <vector> 14 + 15 + namespace digilent { 16 + 17 + class I2C_Client { 18 + public: 19 + class TransmitError : public std::runtime_error { 20 + public: 21 + TransmitError(char const* msg) : std::runtime_error(msg) {} 22 + }; 23 + virtual void read(uint8_t addr, uint8_t* buf, size_t count) = 0; 24 + virtual void write(uint8_t addr, uint8_t const* buf, size_t count) = 0; 25 + virtual ~I2C_Client() = default; 26 + }; 27 + 28 + } /* namespace digilent */ 29 + 30 + #endif /* IICCLIENT_H_ */
+14
sw/src/Zybo-Z7-20-pcam-5c/src/ov5640/OV5640.cpp
··· 1 + /* 2 + * OV5640.cpp 3 + * 4 + * Created on: May 26, 2016 5 + * Author: Elod 6 + */ 7 + 8 + #include "OV5640.h" 9 + 10 + namespace digilent { 11 + 12 + /* TODO: add here configs for IC */ 13 + 14 + } /* namespace digilent */
+954
sw/src/Zybo-Z7-20-pcam-5c/src/ov5640/OV5640.h
··· 1 + /* 2 + * OV5640.h 3 + * 4 + * Created on: May 26, 2016 5 + * Author: Elod 6 + */ 7 + 8 + #ifndef OV5640_H_ 9 + #define OV5640_H_ 10 + 11 + #include <sstream> 12 + #include <iostream> 13 + #include <cstdio> 14 + #include <climits> 15 + 16 + #include "sleep.h" 17 + 18 + #include "I2C_Client.h" 19 + #include "GPIO_Client.h" 20 + #include "../hdmi/VideoOutput.h" 21 + 22 + #define SIZEOF_ARRAY(x) sizeof(x)/sizeof(x[0]) 23 + #define MAP_ENUM_TO_CFG(en, cfg) en, cfg, SIZEOF_ARRAY(cfg) 24 + 25 + namespace digilent 26 + { 27 + 28 + typedef enum {OK=0, ERR_LOGICAL, ERR_GENERAL} Errc; 29 + 30 + namespace OV5640_cfg 31 + { 32 + using config_word_t = struct { uint16_t addr; uint8_t data; }; 33 + using mode_t = enum { 34 + MODE_720P_1280_720_60fps = 0, MODE_1080P_1920_1080_15fps, 35 + MODE_1080P_1920_1080_30fps, MODE_1080P_1920_1080_30fps_336M_MIPI, 36 + MODE_1080P_1920_1080_30fps_336M_1LANE_MIPI, MODE_END 37 + }; 38 + using config_modes_t = struct { mode_t mode; config_word_t const* cfg; size_t cfg_size; }; 39 + using test_t = enum { TEST_DISABLED = 0, TEST_EIGHT_COLOR_BAR, TEST_END }; 40 + using awb_t = enum { AWB_DISABLED = 0, AWB_SIMPLE, AWB_ADVANCED, AWB_END }; 41 + using config_awb_t = struct { awb_t awb; config_word_t const* cfg; size_t cfg_size; }; 42 + using isp_format_t = enum { ISP_RAW = 0, ISP_RGB, ISP_END }; 43 + uint16_t const OV5640_REG_PRE_ISP_TEST_SET1 = 0x503D; 44 + uint16_t const OV5640_FORMAT_MUX_CONTROL = 0x501f; 45 + config_word_t const cfg_advanced_awb_[] = 46 + { 47 + // Enable Advanced AWB 48 + {0x3406 ,0x00}, 49 + {0x5192 ,0x04}, 50 + {0x5191 ,0xf8}, 51 + {0x518d ,0x26}, 52 + {0x518f ,0x42}, 53 + {0x518e ,0x2b}, 54 + {0x5190 ,0x42}, 55 + {0x518b ,0xd0}, 56 + {0x518c ,0xbd}, 57 + {0x5187 ,0x18}, 58 + {0x5188 ,0x18}, 59 + {0x5189 ,0x56}, 60 + {0x518a ,0x5c}, 61 + {0x5186 ,0x1c}, 62 + {0x5181 ,0x50}, 63 + {0x5184 ,0x20}, 64 + {0x5182 ,0x11}, 65 + {0x5183 ,0x00}, 66 + {0x5001 ,0x03} 67 + }; 68 + config_word_t const cfg_simple_awb_[] = 69 + { 70 + // Disable Advanced AWB 71 + {0x518d ,0x00}, 72 + {0x518f ,0x20}, 73 + {0x518e ,0x00}, 74 + {0x5190 ,0x20}, 75 + {0x518b ,0x00}, 76 + {0x518c ,0x00}, 77 + {0x5187 ,0x10}, 78 + {0x5188 ,0x10}, 79 + {0x5189 ,0x40}, 80 + {0x518a ,0x40}, 81 + {0x5186 ,0x10}, 82 + {0x5181 ,0x58}, 83 + {0x5184 ,0x25}, 84 + {0x5182 ,0x11}, 85 + 86 + // Enable simple AWB 87 + {0x3406 ,0x00}, 88 + {0x5183 ,0x80}, 89 + {0x5191 ,0xff}, 90 + {0x5192 ,0x00}, 91 + {0x5001 ,0x03} 92 + }; 93 + config_word_t const cfg_disable_awb_[] = 94 + { 95 + {0x5001 ,0x02} 96 + }; 97 + config_word_t const cfg_720p_60fps_[] = 98 + { 99 + //1280 x 720 binned, RAW10, MIPISCLK=280M, SCLK=56Mz, PCLK=56M 100 + //PLL1 configuration 101 + //[7:4]=0010 System clock divider /2, [3:0]=0001 Scale divider for MIPI /1 102 + {0x3035, 0x21}, 103 + //[7:0]=70 PLL multiplier 104 + {0x3036, 0x46}, 105 + //[4]=0 PLL root divider /1, [3:0]=5 PLL pre-divider /1.5 106 + {0x3037, 0x05}, 107 + //[5:4]=01 PCLK root divider /2, [3:2]=00 SCLK2x root divider /1, [1:0]=01 SCLK root divider /2 108 + {0x3108, 0x11}, 109 + 110 + //[6:4]=001 PLL charge pump, [3:0]=1010 MIPI 10-bit mode 111 + {0x3034, 0x1A}, 112 + 113 + //[3:0]=0 X address start high byte 114 + {0x3800, (0 >> 8) & 0x0F}, 115 + //[7:0]=0 X address start low byte 116 + {0x3801, 0 & 0xFF}, 117 + //[2:0]=0 Y address start high byte 118 + {0x3802, (8 >> 8) & 0x07}, 119 + //[7:0]=0 Y address start low byte 120 + {0x3803, 8 & 0xFF}, 121 + 122 + //[3:0] X address end high byte 123 + {0x3804, (2619 >> 8) & 0x0F}, 124 + //[7:0] X address end low byte 125 + {0x3805, 2619 & 0xFF}, 126 + //[2:0] Y address end high byte 127 + {0x3806, (1947 >> 8) & 0x07}, 128 + //[7:0] Y address end low byte 129 + {0x3807, 1947 & 0xFF}, 130 + 131 + //[3:0]=0 timing hoffset high byte 132 + {0x3810, (0 >> 8) & 0x0F}, 133 + //[7:0]=0 timing hoffset low byte 134 + {0x3811, 0 & 0xFF}, 135 + //[2:0]=0 timing voffset high byte 136 + {0x3812, (0 >> 8) & 0x07}, 137 + //[7:0]=0 timing voffset low byte 138 + {0x3813, 0 & 0xFF}, 139 + 140 + //[3:0] Output horizontal width high byte 141 + {0x3808, (1280 >> 8) & 0x0F}, 142 + //[7:0] Output horizontal width low byte 143 + {0x3809, 1280 & 0xFF}, 144 + //[2:0] Output vertical height high byte 145 + {0x380a, (720 >> 8) & 0x7F}, 146 + //[7:0] Output vertical height low byte 147 + {0x380b, 720 & 0xFF}, 148 + 149 + //HTS line exposure time in # of pixels 150 + {0x380c, (1896 >> 8) & 0x1F}, 151 + {0x380d, 1896 & 0xFF}, 152 + //VTS frame exposure time in # lines 153 + {0x380e, (984 >> 8) & 0xFF}, 154 + {0x380f, 984 & 0xFF}, 155 + 156 + //[7:4]=0x3 horizontal odd subsample increment, [3:0]=0x1 horizontal even subsample increment 157 + {0x3814, 0x31}, 158 + //[7:4]=0x3 vertical odd subsample increment, [3:0]=0x1 vertical even subsample increment 159 + {0x3815, 0x31}, 160 + 161 + //[2]=0 ISP mirror, [1]=0 sensor mirror, [0]=1 horizontal binning 162 + {0x3821, 0x01}, 163 + 164 + //little MIPI shit: global timing unit, period of PCLK in ns * 2(depends on # of lanes) 165 + // 1/56M*2 166 + {0x4837, 36}, 167 + 168 + //Undocumented anti-green settings 169 + //Removes vertical lines appearing under bright light 170 + {0x3618, 0x00}, 171 + {0x3612, 0x59}, 172 + {0x3708, 0x64}, 173 + {0x3709, 0x52}, 174 + {0x370c, 0x03}, 175 + 176 + //[7:4]=0x0 Formatter RAW, [3:0]=0x0 BGBG/GRGR 177 + {0x4300, 0x00}, 178 + //[2:0]=0x3 Format select ISP RAW (DPC) 179 + {0x501f, 0x03} 180 + }; 181 + config_word_t const cfg_1080p_15fps_[] = 182 + { 183 + //1920 x 1080 @ 15 fps, RAW10, MIPISCLK=210, SCLK=42MHz, PCLK=42M 184 + // PLL1 configuration 185 + // [7:4]=0100 System clock divider /4, [3:0]=0001 Scale divider for MIPI /1 186 + {0x3035, 0x41}, 187 + // [7:0]=105 PLL multiplier 188 + {0x3036, 0x69}, 189 + // [4]=0 PLL root divider /1, [3:0]=5 PLL pre-divider /1.5 190 + {0x3037, 0x05}, 191 + // [5:4]=01 PCLK root divider /2, [3:2]=00 SCLK2x root divider /1, [1:0]=01 SCLK root divider /2 192 + {0x3108, 0x11}, 193 + 194 + // [6:4]=001 PLL charge pump, [3:0]=1010 MIPI 10-bit mode 195 + {0x3034, 0x1A}, 196 + 197 + // [3:0]=0 X address start high byte 198 + {0x3800, (336 >> 8) & 0x0F}, 199 + // [7:0]=0 X address start low byte 200 + {0x3801, 336 & 0xFF}, 201 + // [2:0]=0 Y address start high byte 202 + {0x3802, (426 >> 8) & 0x07}, 203 + // [7:0]=0 Y address start low byte 204 + {0x3803, 426 & 0xFF}, 205 + 206 + // [3:0] X address end high byte 207 + {0x3804, (2287 >> 8) & 0x0F}, 208 + // [7:0] X address end low byte 209 + {0x3805, 2287 & 0xFF}, 210 + // [2:0] Y address end high byte 211 + {0x3806, (1529 >> 8) & 0x07}, 212 + // [7:0] Y address end low byte 213 + {0x3807, 1529 & 0xFF}, 214 + 215 + // [3:0]=0 timing hoffset high byte 216 + {0x3810, (16 >> 8) & 0x0F}, 217 + // [7:0]=0 timing hoffset low byte 218 + {0x3811, 16 & 0xFF}, 219 + // [2:0]=0 timing voffset high byte 220 + {0x3812, (12 >> 8) & 0x07}, 221 + // [7:0]=0 timing voffset low byte 222 + {0x3813, 12 & 0xFF}, 223 + 224 + // [3:0] Output horizontal width high byte 225 + {0x3808, (1920 >> 8) & 0x0F}, 226 + // [7:0] Output horizontal width low byte 227 + {0x3809, 1920 & 0xFF}, 228 + // [2:0] Output vertical height high byte 229 + {0x380a, (1080 >> 8) & 0x7F}, 230 + // [7:0] Output vertical height low byte 231 + {0x380b, 1080 & 0xFF}, 232 + 233 + // HTS line exposure time in # of pixels Tline=HTS/sclk 234 + {0x380c, (2500 >> 8) & 0x1F}, 235 + {0x380d, 2500 & 0xFF}, 236 + // VTS frame exposure time in # lines 237 + {0x380e, (1120 >> 8) & 0xFF}, 238 + {0x380f, 1120 & 0xFF}, 239 + 240 + // [7:4]=0x1 horizontal odd subsample increment, [3:0]=0x1 horizontal even subsample increment 241 + {0x3814, 0x11}, 242 + // [7:4]=0x1 vertical odd subsample increment, [3:0]=0x1 vertical even subsample increment 243 + {0x3815, 0x11}, 244 + 245 + // [2]=0 ISP mirror, [1]=0 sensor mirror, [0]=0 no horizontal binning 246 + {0x3821, 0x00}, 247 + 248 + // little MIPI shit: global timing unit, period of PCLK in ns * 2(depends on # of lanes) 249 + {0x4837, 48}, // 1/42M*2 250 + 251 + // Undocumented anti-green settings 252 + // Removes vertical lines appearing under bright light 253 + {0x3618, 0x00}, 254 + {0x3612, 0x59}, 255 + {0x3708, 0x64}, 256 + {0x3709, 0x52}, 257 + {0x370c, 0x03}, 258 + 259 + // [7:4]=0x0 Formatter RAW, [3:0]=0x0 BGBG/GRGR 260 + {0x4300, 0x00}, 261 + // [2:0]=0x3 Format select ISP RAW (DPC) 262 + {0x501f, 0x03} 263 + }; 264 + config_word_t const cfg_1080p_30fps_[] = 265 + { 266 + //1920 x 1080 @ 30fps, RAW10, MIPISCLK=420, SCLK=84MHz, PCLK=84M 267 + //PLL1 configuration 268 + //[7:4]=0010 System clock divider /2, [3:0]=0001 Scale divider for MIPI /1 269 + {0x3035, 0x21}, // 30fps setting 270 + //[7:0]=105 PLL multiplier 271 + {0x3036, 0x69}, 272 + //[4]=0 PLL root divider /1, [3:0]=5 PLL pre-divider /1.5 273 + {0x3037, 0x05}, 274 + //[5:4]=01 PCLK root divider /2, [3:2]=00 SCLK2x root divider /1, [1:0]=01 SCLK root divider /2 275 + {0x3108, 0x11}, 276 + 277 + //[6:4]=001 PLL charge pump, [3:0]=1010 MIPI 10-bit mode 278 + {0x3034, 0x1A}, 279 + 280 + //[3:0]=0 X address start high byte 281 + {0x3800, (336 >> 8) & 0x0F}, 282 + //[7:0]=0 X address start low byte 283 + {0x3801, 336 & 0xFF}, 284 + //[2:0]=0 Y address start high byte 285 + {0x3802, (426 >> 8) & 0x07}, 286 + //[7:0]=0 Y address start low byte 287 + {0x3803, 426 & 0xFF}, 288 + 289 + //[3:0] X address end high byte 290 + {0x3804, (2287 >> 8) & 0x0F}, 291 + //[7:0] X address end low byte 292 + {0x3805, 2287 & 0xFF}, 293 + //[2:0] Y address end high byte 294 + {0x3806, (1529 >> 8) & 0x07}, 295 + //[7:0] Y address end low byte 296 + {0x3807, 1529 & 0xFF}, 297 + 298 + //[3:0]=0 timing hoffset high byte 299 + {0x3810, (16 >> 8) & 0x0F}, 300 + //[7:0]=0 timing hoffset low byte 301 + {0x3811, 16 & 0xFF}, 302 + //[2:0]=0 timing voffset high byte 303 + {0x3812, (12 >> 8) & 0x07}, 304 + //[7:0]=0 timing voffset low byte 305 + {0x3813, 12 & 0xFF}, 306 + 307 + //[3:0] Output horizontal width high byte 308 + {0x3808, (1920 >> 8) & 0x0F}, 309 + //[7:0] Output horizontal width low byte 310 + {0x3809, 1920 & 0xFF}, 311 + //[2:0] Output vertical height high byte 312 + {0x380a, (1080 >> 8) & 0x7F}, 313 + //[7:0] Output vertical height low byte 314 + {0x380b, 1080 & 0xFF}, 315 + 316 + //HTS line exposure time in # of pixels Tline=HTS/sclk 317 + {0x380c, (2500 >> 8) & 0x1F}, 318 + {0x380d, 2500 & 0xFF}, 319 + //VTS frame exposure time in # lines 320 + {0x380e, (1120 >> 8) & 0xFF}, 321 + {0x380f, 1120 & 0xFF}, 322 + 323 + //[7:4]=0x1 horizontal odd subsample increment, [3:0]=0x1 horizontal even subsample increment 324 + {0x3814, 0x11}, 325 + //[7:4]=0x1 vertical odd subsample increment, [3:0]=0x1 vertical even subsample increment 326 + {0x3815, 0x11}, 327 + 328 + //[2]=0 ISP mirror, [1]=0 sensor mirror, [0]=0 no horizontal binning 329 + {0x3821, 0x00}, 330 + 331 + //little MIPI shit: global timing unit, period of PCLK in ns * 2(depends on # of lanes) 332 + {0x4837, 24}, // 1/84M*2 333 + 334 + //Undocumented anti-green settings 335 + //Removes vertical lines appearing under bright light 336 + {0x3618, 0x00}, 337 + {0x3612, 0x59}, 338 + {0x3708, 0x64}, 339 + {0x3709, 0x52}, 340 + {0x370c, 0x03}, 341 + 342 + //[7:4]=0x0 Formatter RAW, [3:0]=0x0 BGBG/GRGR 343 + {0x4300, 0x00}, 344 + //[2:0]=0x3 Format select ISP RAW (DPC) 345 + {0x501f, 0x03} 346 + }; 347 + config_word_t const cfg_1080p_30fps_336M_mipi_[] = 348 + { 349 + //1920 x 1080 @ 30fps, RAW10, MIPISCLK=672, SCLK=67.2MHz, PCLK=134.4M 350 + //PLL1 configuration 351 + //[7:4]=0001 System clock divider /1, [3:0]=0001 Scale divider for MIPI /1 352 + {0x3035, 0x11}, // 30fps setting 353 + //[7:0]=84 PLL multiplier 354 + {0x3036, 0x54}, 355 + //[4]=1 PLL root divider /2, [3:0]=5 PLL pre-divider /1.5 356 + {0x3037, 0x15}, 357 + //[5:4]=00 PCLK root divider /1, [3:2]=00 SCLK2x root divider /1, [1:0]=01 SCLK root divider /2 358 + {0x3108, 0x01}, 359 + 360 + //[6:4]=001 PLL charge pump, [3:0]=1010 MIPI 10-bit mode 361 + {0x3034, 0x1A}, 362 + 363 + //[3:0]=0 X address start high byte 364 + {0x3800, (336 >> 8) & 0x0F}, 365 + //[7:0]=0 X address start low byte 366 + {0x3801, 336 & 0xFF}, 367 + //[2:0]=0 Y address start high byte 368 + {0x3802, (426 >> 8) & 0x07}, 369 + //[7:0]=0 Y address start low byte 370 + {0x3803, 426 & 0xFF}, 371 + 372 + //[3:0] X address end high byte 373 + {0x3804, (2287 >> 8) & 0x0F}, 374 + //[7:0] X address end low byte 375 + {0x3805, 2287 & 0xFF}, 376 + //[2:0] Y address end high byte 377 + {0x3806, (1529 >> 8) & 0x07}, 378 + //[7:0] Y address end low byte 379 + {0x3807, 1529 & 0xFF}, 380 + 381 + //[3:0]=0 timing hoffset high byte 382 + {0x3810, (16 >> 8) & 0x0F}, 383 + //[7:0]=0 timing hoffset low byte 384 + {0x3811, 16 & 0xFF}, 385 + //[2:0]=0 timing voffset high byte 386 + {0x3812, (12 >> 8) & 0x07}, 387 + //[7:0]=0 timing voffset low byte 388 + {0x3813, 12 & 0xFF}, 389 + 390 + //[3:0] Output horizontal width high byte 391 + {0x3808, (1920 >> 8) & 0x0F}, 392 + //[7:0] Output horizontal width low byte 393 + {0x3809, 1920 & 0xFF}, 394 + //[2:0] Output vertical height high byte 395 + {0x380a, (1080 >> 8) & 0x7F}, 396 + //[7:0] Output vertical height low byte 397 + {0x380b, 1080 & 0xFF}, 398 + 399 + //HTS line exposure time in # of pixels Tline=HTS/sclk 400 + {0x380c, (2500 >> 8) & 0x1F}, 401 + {0x380d, 2500 & 0xFF}, 402 + //VTS frame exposure time in # lines 403 + {0x380e, (1120 >> 8) & 0xFF}, 404 + {0x380f, 1120 & 0xFF}, 405 + 406 + //[7:4]=0x1 horizontal odd subsample increment, [3:0]=0x1 horizontal even subsample increment 407 + {0x3814, 0x11}, 408 + //[7:4]=0x1 vertical odd subsample increment, [3:0]=0x1 vertical even subsample increment 409 + {0x3815, 0x11}, 410 + 411 + //[2]=0 ISP mirror, [1]=0 sensor mirror, [0]=0 no horizontal binning 412 + {0x3821, 0x00}, 413 + 414 + //little MIPI shit: global timing unit, period of PCLK in ns * 2(depends on # of lanes) 415 + {0x4837, 14}, // 1/84M*2 416 + 417 + //Undocumented anti-green settings 418 + //Removes vertical lines appearing under bright light 419 + {0x3618, 0x00}, 420 + {0x3612, 0x59}, 421 + {0x3708, 0x64}, 422 + {0x3709, 0x52}, 423 + {0x370c, 0x03}, 424 + 425 + //[7:4]=0x0 Formatter RAW, [3:0]=0x0 BGBG/GRGR 426 + {0x4300, 0x00}, 427 + //[2:0]=0x3 Format select ISP RAW (DPC) 428 + {0x501f, 0x03} 429 + }; 430 + config_word_t const cfg_1080p_30fps_336M_1lane_mipi_[] = 431 + { 432 + //1920 x 1080 @ 30fps, RAW10, MIPISCLK=672, SCLK=67.2MHz, PCLK=134.4M 433 + //PLL1 configuration 434 + //[7:4]=0001 System clock divider /1, 435 + //[3:0]=0001 Scale divider for MIPI /1 436 + {0x3035, 0x11}, // 30fps setting 437 + //[7:0]=84 PLL multiplier 438 + {0x3036, 0x54}, 439 + //[4]=1 PLL root divider /2, [3:0]=5 PLL pre-divider /1.5 440 + {0x3037, 0x15}, 441 + //[5:4]=00 PCLK root divider /1, [3:2]=00 SCLK2x root divider /1, 442 + //[1:0]=01 SCLK root divider /2 443 + {0x3108, 0x01}, 444 + 445 + //[6:4]=001 PLL charge pump, [3:0]=1010 MIPI 10-bit mode 446 + {0x3034, 0x1A}, 447 + 448 + //[7:5]=001 One lane mode, [4]=0 MIPI HS TX no power down, 449 + //[3]=0 MIPI LP RX no power down, [2]=1 MIPI enable, 450 + //[1:0]=10 Debug mode; Default=0x58 451 + {0x300e, 0x25}, 452 + 453 + //[3:0]=0 X address start high byte 454 + {0x3800, (336 >> 8) & 0x0F}, 455 + //[7:0]=0 X address start low byte 456 + {0x3801, 336 & 0xFF}, 457 + //[2:0]=0 Y address start high byte 458 + {0x3802, (426 >> 8) & 0x07}, 459 + //[7:0]=0 Y address start low byte 460 + {0x3803, 426 & 0xFF}, 461 + 462 + //[3:0] X address end high byte 463 + {0x3804, (2287 >> 8) & 0x0F}, 464 + //[7:0] X address end low byte 465 + {0x3805, 2287 & 0xFF}, 466 + //[2:0] Y address end high byte 467 + {0x3806, (1529 >> 8) & 0x07}, 468 + //[7:0] Y address end low byte 469 + {0x3807, 1529 & 0xFF}, 470 + 471 + //[3:0]=0 timing hoffset high byte 472 + {0x3810, (16 >> 8) & 0x0F}, 473 + //[7:0]=0 timing hoffset low byte 474 + {0x3811, 16 & 0xFF}, 475 + //[2:0]=0 timing voffset high byte 476 + {0x3812, (12 >> 8) & 0x07}, 477 + //[7:0]=0 timing voffset low byte 478 + {0x3813, 12 & 0xFF}, 479 + 480 + //[3:0] Output horizontal width high byte 481 + {0x3808, (1920 >> 8) & 0x0F}, 482 + //[7:0] Output horizontal width low byte 483 + {0x3809, 1920 & 0xFF}, 484 + //[2:0] Output vertical height high byte 485 + {0x380a, (1080 >> 8) & 0x7F}, 486 + //[7:0] Output vertical height low byte 487 + {0x380b, 1080 & 0xFF}, 488 + 489 + //HTS line exposure time in # of pixels Tline=HTS/sclk 490 + {0x380c, (2500 >> 8) & 0x1F}, 491 + {0x380d, 2500 & 0xFF}, 492 + //VTS frame exposure time in # lines 493 + {0x380e, (1120 >> 8) & 0xFF}, 494 + {0x380f, 1120 & 0xFF}, 495 + 496 + //[7:4]=0x1 horizontal odd subsample increment, 497 + //[3:0]=0x1 horizontal even subsample increment 498 + {0x3814, 0x11}, 499 + //[7:4]=0x1 vertical odd subsample increment, 500 + //[3:0]=0x1 vertical even subsample increment 501 + {0x3815, 0x11}, 502 + 503 + //[2]=0 ISP mirror, [1]=0 sensor mirror, 504 + //[0]=0 no horizontal binning 505 + {0x3821, 0x00}, 506 + 507 + //little MIPI shit: global timing unit, 508 + //period of PCLK in ns * 2(depends on # of lanes) 509 + {0x4837, 28}, // 1/84M*2 510 + 511 + //Undocumented anti-green settings 512 + // Removes vertical lines appearing under bright light 513 + {0x3618, 0x00}, 514 + {0x3612, 0x59}, 515 + {0x3708, 0x64}, 516 + {0x3709, 0x52}, 517 + {0x370c, 0x03}, 518 + 519 + //[7:4]=0x0 Formatter RAW, [3:0]=0x0 BGBG/GRGR 520 + {0x4300, 0x00}, 521 + //[2:0]=0x3 Format select ISP RAW (DPC) 522 + {0x501f, 0x03} 523 + }; 524 + config_word_t const cfg_init_[] = 525 + { 526 + //[7]=0 Software reset; [6]=1 Software power down; Default=0x02 527 + {0x3008, 0x42}, 528 + //[1]=1 System input clock from PLL; Default read = 0x11 529 + {0x3103, 0x03}, 530 + //[3:0]=0000 MD2P,MD2N,MCP,MCN input; Default=0x00 531 + {0x3017, 0x00}, 532 + //[7:2]=000000 MD1P,MD1N, D3:0 input; Default=0x00 533 + {0x3018, 0x00}, 534 + //[6:4]=001 PLL charge pump, [3:0]=1000 MIPI 8-bit mode 535 + {0x3034, 0x18}, 536 + 537 + // +----------------+ +------------------+ +---------------------+ +---------------------+ 538 + //XVCLK | PRE_DIV0 | | Mult (4+252) | | Sys divider (0=16) | | MIPI divider (0=16) | 539 + //+-------+-----> 3037[3:0]=0001 +--------> 3036[7:0]=0x38 +---------> 3035[7:4]=0001 +--------> 3035[3:0]=0001 | 540 + //12MHz | | / 1 | 12MHz | * 56 | 672MHz | / 1 | 672MHz | / 1 | 541 + // | +----------------+ +------------------+ +----------+----------+ +----------+----------+ 542 + // | | | 543 + // | | MIPISCLK|672MHz 544 + // | | | 545 + // | +----------------+ +------------------+ +----------v----------+ +----------v----------+ 546 + // | | PRE_DIVSP | | R_DIV_SP | | PLL R divider | | MIPI PHY | MIPI_CLK 547 + // +-----> 303d[5:4]=01 +--------> 303d[2]=0 (+1) | | 3037[4]=1 (+1) | | +-------> 548 + // | / 1.5 | 8MHz | / 1 | | / 2 | | / 2 | 336MHz 549 + // +----------------+ +---------+--------+ +----------+----------+ +---------------------+ 550 + // | | 551 + // | | 552 + // | | 553 + // +----------------+ +---------v--------+ +----------v----------+ +---------------------+ 554 + // | SP divider | | Mult | | BIT div (MIPI 8/10) | | SCLK divider | SCLK 555 + // | 303c[3:0]=0x1 +<-------+ 303b[4:0]=0x19 | | 3034[3:0]=0x8) +----+---> 3108[1:0]=01 (2^) +-------> 556 + // | / 1 | 200MHz | * 25 | | / 2 | | | / 2 | 84MHz 557 + // +--------+-------+ +------------------+ +----------+----------+ | +---------------------+ 558 + // | | | 559 + // | | | 560 + // | | | 561 + // +--------v-------+ +----------v----------+ | +---------------------+ 562 + // | R_SELD5 div | ADCCLK | PCLK div | | | SCLK2x divider | 563 + // | 303d[1:0]=001 +-------> | 3108[5:4]=00 (2^) | +---> 3108[3:2]=00 (2^) +-------> 564 + // | / 1 | 200MHz | / 1 | | / 1 | 168MHz 565 + // +----------------+ +----------+----------+ +---------------------+ 566 + // | 567 + // | 568 + // | 569 + // +----------v----------+ +---------------------+ 570 + // | P divider (* #lanes)| PCLK | Scale divider | 571 + // | 3035[3:0]=0001 +--------> 3824[4:0] | 572 + // | / 1 | 168MHz | / 2 | 573 + // +---------------------+ +---------------------+ 574 + 575 + //PLL1 configuration 576 + //[7:4]=0001 System clock divider /1, [3:0]=0001 Scale divider for MIPI /1 577 + {0x3035, 0x11}, 578 + //[7:0]=56 PLL multiplier 579 + {0x3036, 0x38}, 580 + //[4]=1 PLL root divider /2, [3:0]=1 PLL pre-divider /1 581 + {0x3037, 0x11}, 582 + //[5:4]=00 PCLK root divider /1, [3:2]=00 SCLK2x root divider /1, [1:0]=01 SCLK root divider /2 583 + {0x3108, 0x01}, 584 + //PLL2 configuration 585 + //[5:4]=01 PRE_DIV_SP /1.5, [2]=1 R_DIV_SP /1, [1:0]=00 DIV12_SP /1 586 + {0x303D, 0x10}, 587 + //[4:0]=11001 PLL2 multiplier DIV_CNT5B = 25 588 + {0x303B, 0x19}, 589 + {0x3630, 0x2e}, 590 + {0x3631, 0x0e}, 591 + {0x3632, 0xe2}, 592 + {0x3633, 0x23}, 593 + {0x3621, 0xe0}, 594 + {0x3704, 0xa0}, 595 + {0x3703, 0x5a}, 596 + {0x3715, 0x78}, 597 + {0x3717, 0x01}, 598 + {0x370b, 0x60}, 599 + {0x3705, 0x1a}, 600 + {0x3905, 0x02}, 601 + {0x3906, 0x10}, 602 + {0x3901, 0x0a}, 603 + {0x3731, 0x02}, 604 + //VCM debug mode 605 + {0x3600, 0x37}, 606 + {0x3601, 0x33}, 607 + //System control register changing not recommended 608 + {0x302d, 0x60}, 609 + //?? 610 + {0x3620, 0x52}, 611 + {0x371b, 0x20}, 612 + //?? DVP 613 + {0x471c, 0x50}, 614 + {0x3a13, 0x43}, 615 + {0x3a18, 0x00}, 616 + {0x3a19, 0xf8}, 617 + {0x3635, 0x13}, 618 + {0x3636, 0x06}, 619 + {0x3634, 0x44}, 620 + {0x3622, 0x01}, 621 + {0x3c01, 0x34}, 622 + {0x3c04, 0x28}, 623 + {0x3c05, 0x98}, 624 + {0x3c06, 0x00}, 625 + {0x3c07, 0x08}, 626 + {0x3c08, 0x00}, 627 + {0x3c09, 0x1c}, 628 + {0x3c0a, 0x9c}, 629 + {0x3c0b, 0x40}, 630 + //[7]=1 color bar enable, [3:2]=00 eight color bar 631 + {0x503d, 0x00}, 632 + //[2]=1 ISP vflip, [1]=1 sensor vflip 633 + {0x3820, 0x46}, 634 + 635 + //[7:5]=010 Two lane mode, [4]=0 MIPI HS TX no power down, 636 + //[3]=0 MIPI LP RX no power down, [2]=1 MIPI enable, 637 + //[1:0]=10 Debug mode; Default=0x58 638 + {0x300e, 0x45}, 639 + //[5]=0 Clock free running, [4]=1 Send line short packet, 640 + //[3]=0 Use lane1 as default, [2]=1 MIPI bus LP11 when no packet; 641 + //Default=0x04 642 + {0x4800, 0x14}, 643 + {0x302e, 0x08}, 644 + //[7:4]=0x3 YUV422, [3:0]=0x0 YUYV 645 + //{0x4300, 0x30}, 646 + //[7:4]=0x6 RGB565, [3:0]=0x0 {b[4:0],g[5:3],g[2:0],r[4:0]} 647 + {0x4300, 0x6f}, 648 + {0x501f, 0x01}, 649 + 650 + {0x4713, 0x03}, 651 + {0x4407, 0x04}, 652 + {0x440e, 0x00}, 653 + {0x460b, 0x35}, 654 + //[1]=0 DVP PCLK divider manual control by 0x3824[4:0] 655 + {0x460c, 0x20}, 656 + //[4:0]=1 SCALE_DIV=INT(3824[4:0]/2) 657 + {0x3824, 0x01}, 658 + 659 + //MIPI timing 660 + //{0x4805, 0x10}, //LPX global timing select=auto 661 + //{0x4818, 0x00}, //hs_prepare + hs_zero_min ns 662 + //{0x4819, 0x96}, 663 + //{0x482A, 0x00}, //hs_prepare + hs_zero_min UI 664 + // 665 + //{0x4824, 0x00}, //lpx_p_min ns 666 + //{0x4825, 0x32}, 667 + //{0x4830, 0x00}, //lpx_p_min UI 668 + // 669 + //{0x4826, 0x00}, //hs_prepare_min ns 670 + //{0x4827, 0x32}, 671 + //{0x4831, 0x00}, //hs_prepare_min UI 672 + 673 + //[7]=1 LENC correction enabled, 674 + //[5]=1 RAW gamma enabled, 675 + //[2]=1 Black pixel cancellation enabled, 676 + //[1]=1 White pixel cancellation enabled, 677 + //[0]=1 Color interpolation enabled 678 + {0x5000, 0x07}, 679 + //[7]=0 Special digital effects, 680 + //[5]=0 scaling, 681 + //[2]=0 UV average disabled, 682 + //[1]=1 Color matrix enabled, 683 + //[0]=1 Auto white balance enabled 684 + {0x5001, 0x03} 685 + }; 686 + config_modes_t const modes[] = 687 + { 688 + { MAP_ENUM_TO_CFG(MODE_720P_1280_720_60fps, cfg_720p_60fps_) }, 689 + { MAP_ENUM_TO_CFG(MODE_1080P_1920_1080_15fps, cfg_1080p_15fps_) }, 690 + { MAP_ENUM_TO_CFG(MODE_1080P_1920_1080_30fps, cfg_1080p_30fps_), }, 691 + { MAP_ENUM_TO_CFG(MODE_1080P_1920_1080_30fps_336M_MIPI, cfg_1080p_30fps_336M_mipi_) }, 692 + { MAP_ENUM_TO_CFG(MODE_1080P_1920_1080_30fps_336M_1LANE_MIPI, cfg_1080p_30fps_336M_1lane_mipi_) }, 693 + }; 694 + config_awb_t const awbs[] = 695 + { 696 + { MAP_ENUM_TO_CFG(AWB_DISABLED, cfg_disable_awb_) }, 697 + { MAP_ENUM_TO_CFG(AWB_SIMPLE, cfg_simple_awb_) }, 698 + { MAP_ENUM_TO_CFG(AWB_ADVANCED, cfg_advanced_awb_) } 699 + }; 700 + } 701 + 702 + class OV5640 703 + { 704 + public: 705 + class HardwareError; 706 + 707 + OV5640(I2C_Client& iic, GPIO_Client& gpio) : 708 + iic_(iic), gpio_(gpio) 709 + { 710 + reset(); 711 + init(); 712 + } 713 + 714 + void init() 715 + { 716 + uint8_t id_h, id_l; 717 + readReg(reg_ID_h, id_h); 718 + readReg(reg_ID_l, id_l); 719 + 720 + if (id_h != dev_ID_h_ || id_l != dev_ID_l_) 721 + { 722 + /* Does not work. https://www.xilinx.com/support/answers/64193.html 723 + std::stringstream ss; 724 + ss << "Got " << std::hex << id_h << id_l << ". Expected " << dev_ID_h_ << dev_ID_l_; 725 + */ 726 + char msg[100]; 727 + snprintf(msg, 728 + sizeof(msg), 729 + "Got %02x %02x. Expected %02x %02x\r\n", 730 + id_h, id_l, 731 + dev_ID_h_, 732 + dev_ID_l_ 733 + ); 734 + throw HardwareError(HardwareError::WRONG_ID, msg); 735 + } 736 + //[1]=0 System input clock from pad; Default read = 0x11 737 + writeReg(0x3103, 0x11); 738 + //[7]=1 Software reset; [6]=0 Software power down; Default=0x02 739 + writeReg(0x3008, 0x82); 740 + 741 + usleep(1000000); 742 + 743 + size_t i; 744 + for (i = 0; i < sizeof(OV5640_cfg::cfg_init_) / sizeof(OV5640_cfg::cfg_init_[0]); ++i) 745 + { 746 + writeReg( 747 + OV5640_cfg::cfg_init_[i].addr, 748 + OV5640_cfg::cfg_init_[i].data 749 + ); 750 + } 751 + //Stay in power down 752 + } 753 + 754 + Errc reset() 755 + { 756 + //Power cycle 757 + gpio_.clearBit(gpio_.Bits::CAM_GPIO0); 758 + usleep(1000000); 759 + gpio_.setBit(gpio_.Bits::CAM_GPIO0); 760 + usleep(1000000); 761 + 762 + return OK; 763 + } 764 + 765 + Errc set_mode(OV5640_cfg::mode_t mode) 766 + { 767 + if (mode >= OV5640_cfg::mode_t::MODE_END) 768 + return ERR_LOGICAL; 769 + 770 + //[7]=0 Software reset; [6]=1 Software power down; Default=0x02 771 + writeReg(0x3008, 0x42); 772 + 773 + auto cfg_mode = &OV5640_cfg::modes[mode]; 774 + writeConfig(cfg_mode->cfg, cfg_mode->cfg_size); 775 + 776 + //[7]=0 Software reset; [6]=0 Software power down; Default=0x02 777 + writeReg(0x3008, 0x02); 778 + 779 + return OK; 780 + } 781 + 782 + Errc set_awb(OV5640_cfg::awb_t awb) 783 + { 784 + if (awb >= OV5640_cfg::awb_t::AWB_END) 785 + return ERR_LOGICAL; 786 + //[7]=0 Software reset; [6]=1 Software power down; Default=0x02 787 + writeReg(0x3008, 0x42); 788 + 789 + auto cfg_mode = &OV5640_cfg::awbs[awb]; 790 + writeConfig(cfg_mode->cfg, cfg_mode->cfg_size); 791 + 792 + //[7]=0 Software reset; [6]=0 Software power down; Default=0x02 793 + writeReg(0x3008, 0x02); 794 + 795 + return OK; 796 + } 797 + 798 + Errc set_isp_format(OV5640_cfg::isp_format_t isp) 799 + { 800 + if (isp >= OV5640_cfg::isp_format_t::ISP_END) 801 + return ERR_LOGICAL; 802 + //[7]=0 Software reset; [6]=1 Software power down; Default=0x02 803 + writeReg(0x3008, 0x42); 804 + 805 + switch (isp) 806 + { 807 + case OV5640_cfg::isp_format_t::ISP_RGB: 808 + writeReg( 809 + OV5640_cfg::OV5640_FORMAT_MUX_CONTROL, 810 + 0x01 811 + ); 812 + break; 813 + case OV5640_cfg::isp_format_t::ISP_RAW: 814 + writeReg( 815 + OV5640_cfg::OV5640_FORMAT_MUX_CONTROL, 816 + 0x03 817 + ); 818 + break; 819 + default: 820 + break; 821 + } 822 + 823 + //[7]=0 Software reset; [6]=0 Software power down; Default=0x02 824 + writeReg(0x3008, 0x02); 825 + 826 + return OK; 827 + } 828 + 829 + ~OV5640() {} 830 + 831 + void set_test(OV5640_cfg::test_t test) 832 + { 833 + switch (test) 834 + { 835 + case OV5640_cfg::test_t::TEST_DISABLED: 836 + writeReg( 837 + OV5640_cfg::OV5640_REG_PRE_ISP_TEST_SET1, 838 + 0x00 839 + ); 840 + break; 841 + case OV5640_cfg::test_t::TEST_EIGHT_COLOR_BAR: 842 + writeReg( 843 + OV5640_cfg::OV5640_REG_PRE_ISP_TEST_SET1, 844 + 0x80 845 + ); 846 + break; 847 + default: 848 + break; 849 + } 850 + } 851 + 852 + void readReg(uint16_t reg_addr, uint8_t& buf) 853 + { 854 + for (auto retry_count = retry_count_; retry_count > 0; --retry_count) 855 + { 856 + try 857 + { 858 + auto buf_addr = std::vector<uint8_t>{(uint8_t)(reg_addr>>8), (uint8_t)reg_addr}; 859 + iic_.write(dev_address_, buf_addr.data(), buf_addr.size()); 860 + iic_.read(dev_address_, &buf, 1); 861 + break; //If no exceptions, no more retries 862 + } 863 + catch (I2C_Client::TransmitError const& e) 864 + { 865 + if (retry_count > 0) 866 + { 867 + continue; 868 + } 869 + else 870 + { 871 + throw HardwareError(HardwareError::IIC_NACK, e.what()); 872 + } 873 + } 874 + } 875 + } 876 + 877 + void writeReg(uint16_t reg_addr, uint8_t const reg_data) 878 + { 879 + for (auto retry_count = retry_count_; retry_count > 0; --retry_count) 880 + { 881 + try 882 + { 883 + auto buf = std::vector<uint8_t>{(uint8_t)(reg_addr>>8), (uint8_t)reg_addr, reg_data}; 884 + iic_.write(dev_address_, buf.data(), buf.size()); 885 + break; //If no exceptions, no mo retries 886 + } 887 + catch (I2C_Client::TransmitError const& e) 888 + { 889 + if (retry_count > 0) continue; 890 + else throw HardwareError(HardwareError::IIC_NACK, e.what()); 891 + } 892 + } 893 + } 894 + 895 + void writeRegLiquid(uint8_t const reg_data) 896 + { 897 + for (auto retry_count = retry_count_; retry_count > 0; --retry_count) 898 + { 899 + try 900 + { 901 + auto buf = std::vector<uint8_t>{reg_data}; 902 + iic_.write(dev_address2_, buf.data(), buf.size()); 903 + break; //If no exceptions, no mo retries 904 + } 905 + catch (I2C_Client::TransmitError const& e) 906 + { 907 + if (retry_count > 0) continue; 908 + else throw HardwareError(HardwareError::IIC_NACK, e.what()); 909 + } 910 + } 911 + } 912 + 913 + class HardwareError : public std::runtime_error 914 + { 915 + public: 916 + using Errc = enum {WRONG_ID = 1, IIC_NACK}; 917 + HardwareError(Errc errc, char const* msg) : std::runtime_error(msg), errc_(errc) {} 918 + Errc errc() const { return errc_; } 919 + private: 920 + Errc errc_; 921 + }; 922 + 923 + private: 924 + /*void usleep(uint32_t time) 925 + { 926 + //TODO couldn't think of anything better 927 + for (uint32_t i=0; i<time; i++); 928 + // Maybe use a timer from zynq 929 + 930 + }*/ 931 + 932 + void writeConfig(OV5640_cfg::config_word_t const* cfg, size_t cfg_size) 933 + { 934 + for (size_t i=0; i<cfg_size; ++i) 935 + { 936 + writeReg(cfg[i].addr, cfg[i].data); 937 + } 938 + } 939 + 940 + private: 941 + I2C_Client& iic_; 942 + GPIO_Client& gpio_; 943 + uint8_t dev_address_ = (0x78 >> 1); 944 + uint8_t dev_address2_ = (0x46 >> 1); 945 + uint8_t const dev_ID_h_ = 0x56; 946 + uint8_t const dev_ID_l_ = 0x40; 947 + uint16_t const reg_ID_h = 0x300A; 948 + uint16_t const reg_ID_l = 0x300B; 949 + unsigned int const retry_count_ = 10; 950 + }; 951 + 952 + } /* namespace digilent */ 953 + 954 + #endif /* OV5640_H_ */
+98
sw/src/Zybo-Z7-20-pcam-5c/src/ov5640/PS_GPIO.h
··· 1 + /* 2 + * AXI_GPIO.h 3 + * 4 + * Created on: Jun 7, 2016 5 + * Author: Elod 6 + */ 7 + 8 + #ifndef PS_GPIO_H_ 9 + #define PS_GPIO_H_ 10 + 11 + #include <stdexcept> 12 + 13 + #include "GPIO_Client.h" 14 + #include "xgpiops.h" 15 + 16 + namespace digilent { 17 + 18 + template <typename IrptCtl> 19 + class PS_GPIO : public GPIO_Client 20 + { 21 + public: 22 + PS_GPIO(uint32_t dev_id, IrptCtl& irpt_ctl, uint32_t irpt_id) : 23 + drv_inst_(), irpt_ctl_(irpt_ctl), irpt_id_(irpt_id) 24 + { 25 + XGpioPs_Config* config = XGpioPs_LookupConfig(dev_id); 26 + if (config == NULL) { 27 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 28 + } 29 + 30 + XStatus Status; 31 + //Initialize the GPIO driver 32 + Status = XGpioPs_CfgInitialize( 33 + &drv_inst_, 34 + config, 35 + config->BaseAddr 36 + ); 37 + if (Status != XST_SUCCESS) { 38 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 39 + } 40 + 41 + if (XGpioPs_SelfTest(&drv_inst_) != XST_SUCCESS) 42 + { 43 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 44 + } 45 + 46 + XGpioPs_SetOutputEnablePin( 47 + &drv_inst_, 48 + CAM_EN_PIN, 49 + 0 50 + ); 51 + XGpioPs_SetDirectionPin( 52 + &drv_inst_, 53 + CAM_EN_PIN, 54 + 1 55 + ); //Output 56 + XGpioPs_WritePin( 57 + &drv_inst_, 58 + CAM_EN_PIN, 59 + 1 60 + ); 61 + XGpioPs_SetOutputEnablePin( 62 + &drv_inst_, 63 + CAM_EN_PIN, 64 + 1 65 + ); 66 + } 67 + virtual void setBit(Bits bits) 68 + { 69 + switch (bits) 70 + { 71 + case Bits::CAM_GPIO0: 72 + XGpioPs_WritePin(&drv_inst_, CAM_EN_PIN, 1); 73 + break; 74 + } 75 + } 76 + virtual void clearBit(Bits bits) 77 + { 78 + switch (bits) 79 + { 80 + case Bits::CAM_GPIO0: 81 + XGpioPs_WritePin(&drv_inst_, CAM_EN_PIN, 0); 82 + break; 83 + } 84 + } 85 + virtual void commit() 86 + { 87 + 88 + } 89 + private: 90 + XGpioPs drv_inst_; 91 + IrptCtl irpt_ctl_; 92 + u32 irpt_id_; 93 + u32 const CAM_EN_PIN = 54; 94 + }; 95 + 96 + } 97 + 98 + #endif /* PS_GPIO_H_ */
+170
sw/src/Zybo-Z7-20-pcam-5c/src/ov5640/PS_IIC.h
··· 1 + /* 2 + * I2C_ClientAXI_IIC.h 3 + * 4 + * Created on: May 26, 2016 5 + * Author: Elod 6 + */ 7 + 8 + #ifndef I2C_CLIENTAXI_IIC_H_ 9 + #define I2C_CLIENTAXI_IIC_H_ 10 + 11 + #include "I2C_Client.h" 12 + 13 + #include <stdio.h> 14 + #include <stdint.h> 15 + #include <string> 16 + #include <stdexcept> 17 + #include <functional> 18 + 19 + #include "xiicps.h" 20 + 21 + #define STRINGIZE(x) STRINGIZE2(x) 22 + #define STRINGIZE2(x) #x 23 + #define LINE_STRING STRINGIZE(__LINE__) 24 + 25 + namespace digilent { 26 + 27 + using namespace std::placeholders; 28 + 29 + template <typename IrptCtl> 30 + class PS_IIC: public I2C_Client { 31 + public: 32 + 33 + // Shim function to extract function object from CallbackRef and call it 34 + // This should call our member function handlers below 35 + template <typename Func> 36 + static void MyCallback(void* CallbackRef, u32 StatusEvent) 37 + { 38 + auto pfn = static_cast<Func*>(CallbackRef); 39 + pfn->operator()(StatusEvent); 40 + } 41 + 42 + PS_IIC(uint32_t dev_id, IrptCtl& irpt_ctl, uint32_t irpt_id, uint32_t sclk_rate_Hz) : 43 + drv_inst_(), 44 + irpt_ctl_(irpt_ctl), 45 + stat_handler_(std::bind(&PS_IIC::StatusHandler, this, _1)) 46 + { 47 + XIicPs_Config* ConfigPtr; 48 + XStatus Status; 49 + 50 + // Initialize the IIC driver so that it is ready to use. 51 + ConfigPtr = XIicPs_LookupConfig(dev_id); 52 + if (ConfigPtr == NULL) { 53 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 54 + } 55 + 56 + Status = XIicPs_CfgInitialize(&drv_inst_, ConfigPtr, 57 + ConfigPtr->BaseAddress); 58 + if (Status != XST_SUCCESS) { 59 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 60 + } 61 + 62 + Status = XIicPs_SelfTest(&drv_inst_); 63 + if (Status != XST_SUCCESS) 64 + { 65 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 66 + } 67 + 68 + Status = XIicPs_SetSClk(&drv_inst_, sclk_rate_Hz); 69 + if (Status != XST_SUCCESS) 70 + { 71 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 72 + } 73 + 74 + //Register the IIC handler with the interrupt controller 75 + irpt_ctl_.registerHandler(irpt_id, 76 + reinterpret_cast<typename IrptCtl::Handler>(&XIicPs_MasterInterruptHandler), 77 + &drv_inst_ 78 + ); 79 + irpt_ctl_.enableInterrupt(irpt_id); 80 + irpt_ctl_.enableInterrupts(); 81 + 82 + XIicPs_SetStatusHandler(&drv_inst_, 83 + &stat_handler_, 84 + &MyCallback<decltype(stat_handler_)> 85 + ); 86 + } 87 + 88 + virtual void read(uint8_t addr, uint8_t* buf, size_t count) override 89 + { 90 + // Receive the Data. 91 + 92 + resetFlags(); 93 + 94 + XIicPs_MasterRecv(&drv_inst_, buf, count, addr); 95 + 96 + // Wait till all the data is received. 97 + while (!rx_complete_flag_ && !slave_nack_flag_ && !arb_lost_flag_ && !other_error_flag_); 98 + 99 + if (slave_nack_flag_) throw TransmitError("Slave NACK"); 100 + if (arb_lost_flag_) throw TransmitError("Arbitration lost"); 101 + if (other_error_flag_) throw TransmitError("Other I2C error"); 102 + } 103 + 104 + virtual void write(uint8_t addr, uint8_t const* buf, size_t count) override 105 + { 106 + //xintc.h is not const-correct, so we create local copy 107 + std::vector<uint8_t> buf_local(count); 108 + buf_local.assign(buf, buf+count); 109 + 110 + resetFlags(); 111 + 112 + XIicPs_MasterSend(&drv_inst_, buf_local.data(), buf_local.size(), addr); 113 + 114 + while (!tx_complete_flag_ && !slave_nack_flag_ && !arb_lost_flag_ && !other_error_flag_); 115 + 116 + if (slave_nack_flag_) throw TransmitError("Slave NACK"); 117 + if (arb_lost_flag_) throw TransmitError("Arbitration lost"); 118 + if (other_error_flag_) throw TransmitError("Other I2C error"); 119 + } 120 + 121 + ~PS_IIC() {} 122 + 123 + private: 124 + void StatusHandler(int Event) 125 + { 126 + if (Event & XIICPS_EVENT_COMPLETE_SEND) //Transmit Complete Event 127 + { 128 + tx_complete_flag_ = 1; 129 + } 130 + if (Event & XIICPS_EVENT_COMPLETE_RECV) //Receive Complete Event 131 + { 132 + rx_complete_flag_ = 1; 133 + } 134 + if (Event & XIICPS_EVENT_NACK) // Slave did not ACK (had error) 135 + { 136 + slave_nack_flag_ = 1; 137 + } 138 + if (Event & XIICPS_EVENT_ARB_LOST) // Arbitration was lost 139 + { 140 + arb_lost_flag_ = 1; 141 + } 142 + if (Event & (XIICPS_EVENT_TIME_OUT | //Transfer timed out 143 + XIICPS_EVENT_ERROR | // Receive error 144 + XIICPS_EVENT_SLAVE_RDY)) // Bus transitioned to not busy 145 + { 146 + other_error_flag_ = 1; 147 + } 148 + } 149 + void resetFlags() 150 + { 151 + tx_complete_flag_ = 0; // Flag to check completion of Transmission 152 + rx_complete_flag_ = 0; // Flag to check completion of Reception 153 + slave_nack_flag_ = 0; // Flag to check for NACK error 154 + arb_lost_flag_ = 0; // Flag to check for arbitration lost error 155 + other_error_flag_ = 0; 156 + } 157 + private: 158 + XIicPs drv_inst_; 159 + IrptCtl& irpt_ctl_; 160 + std::function<void(int)> stat_handler_; 161 + volatile uint8_t tx_complete_flag_; // Flag to check completion of Transmission 162 + volatile uint8_t rx_complete_flag_; // Flag to check completion of Reception 163 + volatile uint8_t slave_nack_flag_; // Flag to check completion of Reception 164 + volatile uint8_t arb_lost_flag_; // Flag to check completion of Reception 165 + volatile uint8_t other_error_flag_; // Flag to check completion of Transmission 166 + }; 167 + 168 + } /* namespace digilent */ 169 + 170 + #endif /* I2C_CLIENTAXI_IIC_H_ */
+116
sw/src/Zybo-Z7-20-pcam-5c/src/ov5640/ScuGicInterruptController.h
··· 1 + /* 2 + * IInterruptController.h 3 + * 4 + * Created on: May 27, 2016 5 + * Author: Elod 6 + */ 7 + 8 + #ifndef IINTERRUPTCONTROLLER_H_ 9 + #define IINTERRUPTCONTROLLER_H_ 10 + 11 + #include <stdexcept> 12 + 13 + #include "xscugic.h" 14 + 15 + #define STRINGIZE(x) STRINGIZE2(x) 16 + #define STRINGIZE2(x) #x 17 + #define LINE_STRING STRINGIZE(__LINE__) 18 + 19 + namespace digilent { 20 + 21 + class ScuGicInterruptController 22 + { 23 + public: 24 + typedef Xil_InterruptHandler Handler; 25 + typedef XStatus Errc; 26 + ScuGicInterruptController(uint32_t dev_id) : 27 + drv_inst_() 28 + { 29 + XScuGic_Config* config = XScuGic_LookupConfig(dev_id); 30 + if (config == NULL) 31 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 32 + 33 + XStatus Status; 34 + // Initialize the Intc driver so that it is ready to use. 35 + Status = XScuGic_CfgInitialize( 36 + &drv_inst_, 37 + config, 38 + config->CpuBaseAddress 39 + ); 40 + if (Status != XST_SUCCESS) { 41 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 42 + } 43 + 44 + Status = XScuGic_SelfTest(&drv_inst_); 45 + if (Status != XST_SUCCESS) { 46 + throw std::runtime_error(__FILE__ ":" LINE_STRING); 47 + } 48 + } 49 + Errc enableInterrupts() 50 + { 51 + // Connect the interrupt controller interrupt handler to the hardware 52 + // interrupt handling logic in the ARM processor. 53 + 54 + Xil_ExceptionRegisterHandler( 55 + XIL_EXCEPTION_ID_INT, 56 + (Xil_ExceptionHandler) XScuGic_InterruptHandler, 57 + &drv_inst_ 58 + ); 59 + 60 + // Enable interrupts in the ARM 61 + Xil_ExceptionEnable(); 62 + 63 + return XST_SUCCESS; 64 + } 65 + 66 + Errc disableInterrupts() 67 + { 68 + Xil_ExceptionDisable(); 69 + return XST_SUCCESS; 70 + } 71 + 72 + template <typename ...Arg> 73 + Errc registerHandler(uint32_t irpt_id, 74 + Handler handler, 75 + //void *CallbackRef 76 + Arg&& ...args 77 + ) 78 + { 79 + XStatus Status; 80 + 81 + Status = XScuGic_Connect(&drv_inst_, 82 + irpt_id, 83 + handler, 84 + //CallbackRef 85 + std::forward<Arg>(args)... 86 + ); 87 + 88 + if (Status != XST_SUCCESS) { 89 + return XST_FAILURE; 90 + } 91 + 92 + //Enable the interrupts for the IIC device. 93 + XScuGic_Enable(&drv_inst_, irpt_id); 94 + 95 + return XST_SUCCESS; 96 + } 97 + 98 + Errc disableInterrupt(uint32_t irpt_id) 99 + { 100 + XScuGic_Disable(&drv_inst_, irpt_id); 101 + return XST_SUCCESS; 102 + } 103 + 104 + Errc enableInterrupt(uint32_t irpt_id) 105 + { 106 + XScuGic_Enable(&drv_inst_, irpt_id); 107 + return XST_SUCCESS; 108 + } 109 + 110 + private: 111 + XScuGic drv_inst_; 112 + }; 113 + 114 + } /* namespace digilent */ 115 + 116 + #endif /* IINTERRUPTCONTROLLER_H_ */
+86
sw/src/Zybo-Z7-20-pcam-5c/src/platform.c
··· 1 + /****************************************************************************** 2 + * Copyright (C) 2023 Advanced Micro Devices, Inc. All Rights Reserved. 3 + * SPDX-License-Identifier: MIT 4 + ******************************************************************************/ 5 + 6 + #include "xparameters.h" 7 + #include "xil_cache.h" 8 + 9 + #ifndef SDT 10 + #include "platform_config.h" 11 + #endif 12 + 13 + /* 14 + * Uncomment one of the following two lines, depending on the target, 15 + * if ps7/psu init source files are added in the source directory for 16 + * compiling example outside of SDK. 17 + */ 18 + /*#include "ps7_init.h"*/ 19 + /*#include "psu_init.h"*/ 20 + 21 + #ifdef STDOUT_IS_16550 22 + #include "xuartns550_l.h" 23 + 24 + #define UART_BAUD 9600 25 + #endif 26 + 27 + void 28 + enable_caches() 29 + { 30 + #ifdef __PPC__ 31 + Xil_ICacheEnableRegion(CACHEABLE_REGION_MASK); 32 + Xil_DCacheEnableRegion(CACHEABLE_REGION_MASK); 33 + #elif __MICROBLAZE__ 34 + #ifdef XPAR_MICROBLAZE_USE_ICACHE 35 + Xil_ICacheEnable(); 36 + #endif 37 + #ifdef XPAR_MICROBLAZE_USE_DCACHE 38 + Xil_DCacheEnable(); 39 + #endif 40 + #endif 41 + } 42 + 43 + void 44 + disable_caches() 45 + { 46 + #ifdef __MICROBLAZE__ 47 + #ifdef XPAR_MICROBLAZE_USE_DCACHE 48 + Xil_DCacheDisable(); 49 + #endif 50 + #ifdef XPAR_MICROBLAZE_USE_ICACHE 51 + Xil_ICacheDisable(); 52 + #endif 53 + #endif 54 + } 55 + 56 + void 57 + init_uart() 58 + { 59 + #ifdef STDOUT_IS_16550 60 + XUartNs550_SetBaud(STDOUT_BASEADDR, XPAR_XUARTNS550_CLOCK_HZ, UART_BAUD); 61 + XUartNs550_SetLineControlReg(STDOUT_BASEADDR, XUN_LCR_8_DATA_BITS); 62 + #endif 63 + /* Bootrom/BSP configures PS7/PSU UART to 115200 bps */ 64 + } 65 + 66 + void 67 + init_platform() 68 + { 69 + /* 70 + * If you want to run this example outside of SDK, 71 + * uncomment one of the following two lines and also #include "ps7_init.h" 72 + * or #include "ps7_init.h" at the top, depending on the target. 73 + * Make sure that the ps7/psu_init.c and ps7/psu_init.h files are included 74 + * along with this example source files for compilation. 75 + */ 76 + /* ps7_init();*/ 77 + /* psu_init();*/ 78 + enable_caches(); 79 + init_uart(); 80 + } 81 + 82 + void 83 + cleanup_platform() 84 + { 85 + disable_caches(); 86 + }
+16
sw/src/Zybo-Z7-20-pcam-5c/src/platform.h
··· 1 + /****************************************************************************** 2 + * Copyright (C) 2023 Advanced Micro Devices, Inc. All Rights Reserved. 3 + * SPDX-License-Identifier: MIT 4 + ******************************************************************************/ 5 + 6 + #ifndef __PLATFORM_H_ 7 + #define __PLATFORM_H_ 8 + 9 + #ifndef SDT 10 + #include "platform_config.h" 11 + #endif 12 + 13 + void init_platform(); 14 + void cleanup_platform(); 15 + 16 + #endif
+48
sw/src/Zybo-Z7-20-pcam-5c/src/platform/platform.h
··· 1 + /****************************************************************************** 2 + * 3 + * Copyright (C) 2008 - 2014 Xilinx, Inc. All rights reserved. 4 + * 5 + * Permission is hereby granted, free of charge, to any person obtaining a copy 6 + * of this software and associated documentation files (the "Software"), to deal 7 + * in the Software without restriction, including without limitation the rights 8 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 + * copies of the Software, and to permit persons to whom the Software is 10 + * furnished to do so, subject to the following conditions: 11 + * 12 + * The above copyright notice and this permission notice shall be included in 13 + * all copies or substantial portions of the Software. 14 + * 15 + * Use of the Software is limited solely to applications: 16 + * (a) running on a Xilinx device, or 17 + * (b) that interact with a Xilinx device through a bus or interconnect. 18 + * 19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 + * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 24 + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 + * SOFTWARE. 26 + * 27 + * Except as contained in this notice, the name of the Xilinx shall not be used 28 + * in advertising or otherwise to promote the sale, use or other dealings in 29 + * this Software without prior written authorization from Xilinx. 30 + * 31 + ******************************************************************************/ 32 + 33 + #ifndef __PLATFORM_H_ 34 + #define __PLATFORM_H_ 35 + 36 + #include "platform_config.h" 37 + 38 + #define IS_Z7020 ((( Xil_In32 (XPS_SYS_CTRL_BASEADDR + 0x530) >> 12 ) & 0x1F) == (7)) 39 + #define IS_Z7010 ((( Xil_In32 (XPS_SYS_CTRL_BASEADDR + 0x530) >> 12 ) & 0x1F) == (2)) 40 + 41 + void init_platform(); 42 + void cleanup_platform(); 43 + void flush_dcache(); 44 + void disable_caches(); 45 + void enable_caches(); 46 + void ps_reset(); 47 + 48 + #endif
+4
sw/src/Zybo-Z7-20-pcam-5c/src/platform/platform_config.h
··· 1 + #ifndef __PLATFORM_CONFIG_H_ 2 + #define __PLATFORM_CONFIG_H_ 3 + 4 + #endif
sw/src/system_wrapper/system_wrapper.xsa

This is a binary file and will not be displayed.