rust-embedded / svdtools Goto Github PK
View Code? Open in Web Editor NEWPython package to handle vendor-supplied, often buggy SVD files.
License: Apache License 2.0
Python package to handle vendor-supplied, often buggy SVD files.
License: Apache License 2.0
derive_register()
contains the following code:
rcopy = copy.deepcopy(source)
rcopy.find("name").text = rname
rcopy.find("displayName").text = rname
The RP2040 SVD, however, does not define any displayName
, so the last line causes AttributeError: 'NoneType' object has no attribute 'text'
.
The following modification fixes the problem:
if rcopy.find("displayName") != None:
rcopy.find("displayName").text = rname
I am trying to solve #9 and I noticed that the patch
command has no tests.
If you want to help me you can provide here some test cases ๐
You should provide: test description, input svd and yaml.
You don't have to provide also the patched svd (the output), since I can obtain it by launching the python script.
Modify register field.
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<device schemaVersion="1.1"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:noNamespaceSchemaLocation="CMSIS-SVD_Schema_1_1.xsd">
<name>STM32L4x2</name>
<version>1.6</version>
<description>STM32L4x2</description>
<!-- details about the cpu embedded in the device -->
<cpu>
<name>CM4</name>
<revision>r1p0</revision>
<endian>little</endian>
<mpuPresent>false</mpuPresent>
<fpuPresent>false</fpuPresent>
<nvicPrioBits>3</nvicPrioBits>
<vendorSystickConfig>false</vendorSystickConfig>
</cpu>
<!--Bus Interface Properties-->
<!--Cortex-M3 is byte addressable-->
<addressUnitBits>8</addressUnitBits>
<!--the maximum data bit width accessible within a single transfer-->
<width>32</width>
<!--Register Default Properties-->
<size>0x20</size>
<resetValue>0x0</resetValue>
<resetMask>0xFFFFFFFF</resetMask>
<peripherals>
<peripheral>
<name>DAC1</name>
<description>Digital-to-analog converter</description>
<groupName>DAC</groupName>
<baseAddress>0x40007400</baseAddress>
<addressBlock>
<offset>0x0</offset>
<size>0x400</size>
<usage>registers</usage>
</addressBlock>
<registers>
<register>
<name>CR</name>
<displayName>CR</displayName>
<description>control register</description>
<addressOffset>0x0</addressOffset>
<size>0x20</size>
<access>read-write</access>
<resetValue>0x00000000</resetValue>
<fields>
<field>
<name>EN1</name>
<description>DAC channel1 enable</description>
<bitOffset>0</bitOffset>
<bitWidth>1</bitWidth>
</field>
</fields>
</register>
</registers>
</peripheral>
</peripherals>
</device>
_svd: stm32l4x2.svd
# SVD incorrectly labels APB1ENR1 bit 18 as USART1EN instead of USART3EN.
# SVD incorrectly labels APB1ENR1 bit 26 as USBF instead of USBFSEN.
DAC1:
CR:
_modify:
EN1:
name: EN2
description: EN2 description
As I can see derive_register
and derive_peripheral
are semantically different. It is more similar to copy_peripheral
to derive them
I have a peripheral with a number of registers, each 64 bits long. Within each register is one 40 bit long field.
Trying to merge these registers into an array fails with the following error message:
Traceback (most recent call last):
File ".venv/bin/svd", line 8, in <module>
sys.exit(svdtools_cli())
File "/mnt/btrfs/svdtools/.venv/lib/python3.8/site-packages/click/core.py", line 764, in __call__
return self.main(*args, **kwargs)
File "/mnt/btrfs/svdtools/.venv/lib/python3.8/site-packages/click/core.py", line 717, in main
rv = self.invoke(ctx)
File "/mnt/btrfs/svdtools/.venv/lib/python3.8/site-packages/click/core.py", line 1137, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/mnt/btrfs/svdtools/.venv/lib/python3.8/site-packages/click/core.py", line 956, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/mnt/btrfs/svdtools/.venv/lib/python3.8/site-packages/click/core.py", line 555, in invoke
return callback(*args, **kwargs)
File "/mnt/btrfs/svdtools/.venv/lib/python3.8/site-packages/svdtools/cli.py", line 16, in patch
svdtools.patch.main(yaml_file)
File "/mnt/btrfs/svdtools/.venv/lib/python3.8/site-packages/svdtools/patch.py", line 1332, in main
process_device(svd, root)
File "/mnt/btrfs/svdtools/.venv/lib/python3.8/site-packages/svdtools/patch.py", line 1309, in process_device
d.process_peripheral(periphspec, device[periphspec], update_fields)
File "/mnt/btrfs/svdtools/.venv/lib/python3.8/site-packages/svdtools/patch.py", line 665, in process_peripheral
p.collect_in_array(rspec, rmod)
File "/mnt/btrfs/svdtools/.venv/lib/python3.8/site-packages/svdtools/patch.py", line 878, in collect_in_array
bitmasks = [Register(r[0]).get_bitmask() for r in registers]
File "/mnt/btrfs/svdtools/.venv/lib/python3.8/site-packages/svdtools/patch.py", line 878, in <listcomp>
bitmasks = [Register(r[0]).get_bitmask() for r in registers]
File "/mnt/btrfs/svdtools/.venv/lib/python3.8/site-packages/svdtools/patch.py", line 1259, in get_bitmask
mask |= (0xFFFFFFFF >> (32 - fwidth)) << foffset
ValueError: negative shift count
make: *** [Makefile:12: example] Error 1
I have created a minimum failing example that fits neatly into the example from the repo:
_add:
EXAMPLE:
registers:
REG0:
addressOffset: "0x0000000"
size: 0x40
fields:
FIELD:
bitOffset: 0
bitWidth: 33
REG1:
addressOffset: "0x0000008"
size: 0x40
fields:
FIELD:
bitOffset: 0
bitWidth: 33
EXAMPLE:
_array:
REG*: {}
I have played around a bit, and the patch seems to generate fine as long as the field is shorter than 32 bits, even if I offset it into the top half of the register.
(Found on v0.1.13)
I've tried to add
_derive:
TIM5: TIM2
in stm32l552.yaml
, but after this
TIM2:
_delete:
_interrupts:
- TIM2_*
doesn't work.
If I try to first _copy
(or _rebase
) a peripheral and then delete the original it does not work. This is the simplest reproduction of this issue:
_svd: svd/stm32g070.svd
_copy:
TIM3:
from: TIM2
_delete:
- TIM2
It crashes with the error
svdtools.patch.SvdPatchError: peripheral None not found
How is the order of operations defined? It seems like _delete
is done before _copy
. If I remove the _delete
, the _copy
works fine. Is there a workaround?
I want to rename some register blocks, and their respective bitfields on a given peripheral. Here is my yaml:
SYSTIMER:
_modify:
VALUE_LO:
name: UNIT0_VALUE_LO
VALUE_HI:
name: UNIT0_VALUE_HI
UPDATE:
name: UNIT0_OP
fields:
TIMER_VALUE_VALID:
name: TIMER_UNIT0_VALUE_VALID
TIMER_UPDATE:
name: TIMER_UNIT0_UPDATE
The registers are correctly renamed, but when I try and rename the bit fields I get the following error:
Error: Processing device `ESP32-S2`
Caused by:
0: According to `SYSTIMER`
1: Processing peripheral `SYSTIMER`
2: Modifying registers matched to `UPDATE`
3: `Build error: `bit_range` must be initialized
Have I got the syntax wrong, or is this a bug?
Hi,
I'm working on the SVD -> PAC for stm32l4r5. The CH7WDATR register in DFSDM1 is duplicated/misnamed, the second register should presumably be CH7WDATINR. How do I rename only the second register?
Best regards, Gaute
Hello! The current state of the tool is very limited. Can you add regex to it?
The _array
KEY is useful for aggregating existing registers but I'd like to request functionality to create new arrays without first _add
ing all the individual registers.
I pulled down the repository and tried to run make. After setting up python venv, I'm getting:
make: venv/bin/pip: Command not found
Am I missing some critical first step here? Forgive me, I've never used python venv before.
Consider the following register layout in a pre-generated SVD file:
<register>
<name>TACCR0</name>
<description>Timer A Capture/Compare 0</description>
<addressOffset>68</addressOffset>
<size>16</size>
<resetMask>65535</resetMask>
</register>
along with the following YAML file (_svd points to the right place):
_svd: ../../msp430g2211.svd
"TIMER_A2":
TACCR0:
_add:
TACCR0:
description: "Timer A capture/compare register 0"
bitOffset: 0
bitWidth: 16
svd
will die with the following backtrace:
$ svd patch overrides/devices/msp430g2211.yaml
Traceback (most recent call last):
File "C:/msys64/mingw64/lib/python3.8/runpy.py", line 193, in _run_module_as_main
return _run_code(code, main_globals, None,
File "C:/msys64/mingw64/lib/python3.8/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "C:/msys64/mingw64/bin/svd.exe/__main__.py", line 7, in <module>
File "C:/msys64/mingw64/lib/python3.8/site-packages/click/core.py", line 829, in __call__
return self.main(*args, **kwargs)
File "C:/msys64/mingw64/lib/python3.8/site-packages/click/core.py", line 782, in main
rv = self.invoke(ctx)
File "C:/msys64/mingw64/lib/python3.8/site-packages/click/core.py", line 1259, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "C:/msys64/mingw64/lib/python3.8/site-packages/click/core.py", line 1066, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "C:/msys64/mingw64/lib/python3.8/site-packages/click/core.py", line 610, in invoke
return callback(*args, **kwargs)
File "C:/msys64/mingw64/lib/python3.8/site-packages/svdtools/cli.py", line 16, in patch
svdtools.patch.main(yaml_file)
File "C:/msys64/mingw64/lib/python3.8/site-packages/svdtools/patch.py", line 1025, in main
process_device(svd, root)
File "C:/msys64/mingw64/lib/python3.8/site-packages/svdtools/patch.py", line 1005, in process_device
d.process_peripheral(periphspec, device[periphspec], update_fields)
File "C:/msys64/mingw64/lib/python3.8/site-packages/svdtools/patch.py", line 434, in process_peripheral
p.process_register(rspec, register, update_fields)
File "C:/msys64/mingw64/lib/python3.8/site-packages/svdtools/patch.py", line 756, in process_register
r.add_field(fname, fadd)
File "C:/msys64/mingw64/lib/python3.8/site-packages/svdtools/patch.py", line 834, in add_field
for ftag in parent.iter("field"):
AttributeError: 'NoneType' object has no attribute 'iter'
According to IRC:
(5:12:22 AM) agg: hah, yes, I see the issue
(5:12:43 AM) agg: the backtrace you're hitting is when it goes through existing fields on the register to check you're not adding a duplicate name
(5:12:51 AM) agg: but there's no <fields> member in this register at all
Workaround for now is to delete the register completely and recreate it:
TIMER_A2:
_delete:
- TACCR0
_add:
TACCR0:
description: Timer A Capture/Compare 0
addressOffset: 68
size: 16
resetMask: 65535
fields:
TACCR0:
description: Timer A capture/compare register 0
bitOffset: 0
bitWidth: 16
The Atmel SAML10 chips have a somewhat odd structure for their UART/SPI/I2C peripherals. There are a couple of single SERCOM peripherals, which can be configured into one of those modes based on a MODE register, whose offset is the same for all modes.
The Atmel-provided SVD files model this like so:
<peripheral>
<name>SERCOM0</name>
<registers>
<cluster><name>I2CM</name>
<register>
<name>CTRLA</name>
<fields>
<field><name>SDAHOLD</name></field>
....
</fields>
</register>
...
</cluster>
<cluster><name>SPI</name>
<register>
<name>CTRLA</name>
<fields>
<field><name>CPHA</name></field>
....
</fields>
</register>
</cluster>
</registers>
</peripheral>
That is, there's a cluster for each independent configuration of the peripheral, with the same register name defined, and different fields defined. (SDAHOLD does not exist in SPI mode, and CPHA does not exist in I2C mode.) Other fields, such as MODE, are in both.
I don't see a way to select just one of these clusters to modify. If I match on CTRLA then I can't match on the right fields, because the selector code in patch.py returns all four of the CTRLA register tags for all four clusters. If I try to introduce a _cluster: entry in the YAML then the code insists on grouping all four of the CTRLA registers together into a block, and failing to validate the offsets or the bitmasks.
Is there a way to use the cluster name purely for selection, instead of for cluster creation? If not, can there be?
I'm using dimArrayIndex
to simplify access to array elements (register arrays). The element has been introduced with SVD version 1.3.2 and is not supported by svdtools
.
On the one hand, it doesn't seem to be possible to define enumeration values for registers and patch them into an SVD file.
And on the other hand, the patch process aborts (quits) as soon as dimArrayIndex
is used in the SVD file which is supposed to be patched. It must be removed to successfully patch the file and inserted again afterwards.
Is there any plan to support this?
Both the Python and Rust mmaps
command show registers with derivedFrom
set as having no fields; this property is only processed for peripherals at the moment.
There is a failing test:
Left: test.d: \\?\D:\Users\Hydra\Documents\dev\projects\stm32-rs\svdtools\res\makedeps\sub-tests\inc1.yaml \\?\D:\Users\Hydra\Documents\dev\projects\stm32-rs\svdtools\res\makedeps\sub-tests\inc2.yaml
Right: test.d: D:\Users\Hydra\Documents\dev\projects\stm32-rs\svdtools\res\makedeps\sub-tests/inc1.yaml D:\Users\Hydra\Documents\dev\projects\stm32-rs\svdtools\res\makedeps\sub-tests/inc2.yaml
The use of std::fs::canonicalize
is adding \\?\
in addition to removing \.\
path components.
These paths are not valid paths when svdtools
is used as part of stm32-rs
when running make patch
in cygwin.
The resulting error from the command that uses the generated dependencies make svd2rust
is as follows:
$ make svd2rust
.deps/stm32c011.d:1: *** target pattern contains no '%'. Stop.
If you inspect the generated file you see this:
$ more .deps/stm32c011.d
stm32c011.d: \\?\D:\Users\Hydra\Documents\dev\projects\stm32-rs\stm32-rs\devices\common_patches\c0.yaml \\?\D:\Users\Hydra\Documents\dev\projects\stm32-rs\stm32-rs\devices\common_patches\nvic\2_prio_bits.yaml
As a workaround I hacked up abspath
as follows:
/// Gets the absolute path of relpath from the point of view of frompath.
fn abspath(frompath: &Path, relpath: &Path) -> Result<PathBuf, std::io::Error> {
//std::fs::canonicalize(frompath.parent().unwrap().join(relpath))
let path = frompath.parent().unwrap().join(relpath);
let path_str = format!("{}", path.display()).replace("\\", "/");
Result::<_,std::io::Error>::Ok(PathBuf::from(path_str))
}
Branch with that is here: https://github.com/hydra/svdtools/tree/working-windows-makedeps
and now the test fails as follows:
Left: test.d: D:/Users/Hydra/Documents/dev/projects/stm32-rs/svdtools/res/makedeps/sub-tests/inc1.yaml D:/Users/Hydra/Documents/dev/projects/stm32-rs/svdtools/res/makedeps/sub-tests/inc2.yaml
Right: test.d: D:\Users\Hydra\Documents\dev\projects\stm32-rs\svdtools\res\makedeps\sub-tests/inc1.yaml D:\Users\Hydra\Documents\dev\projects\stm32-rs\svdtools\res\makedeps\sub-tests/inc2.yaml
However, the resulting .d
files are now valid, here's the same one from the stm32-rs project from before:
$ more .deps/stm32c011.d
stm32c011.d: devices/./common_patches/c0.yaml devices/./common_patches/nvic/2_prio_bits.yaml
I'm no expert on the String, PathBuf or FS APIs so not sure what a proper cross-platform fix is, but this unblocked me today.
which is not correct for read-only and write-only fields
Field with *
matching only patches the first occurrence of the match:
SYSCON:
STARTERP1:
"SPI*":
_replace_enum:
DISABLED: [0, Disabled]
ENABLED: [1, Enabled]
this only matches SPI0, and not SPI1. I'm not sure if this is an intended behavior or if this is a bug?
applicable svd: https://gist.github.com/allexoll/2dc8d7ca2eca44bfe2b17f0c0769eba7
My question is about this check:
https://github.com/stm32-rs/svdtools/blob/d8521cd0dc0314365097edcac75ccbb1fa19864c/svdtools/patch.py#L1037-L1038
Is it necessary those checks to be hard error?
It is often particular chips don't have some registers. And we need to create individual rule for them which complicates all patch system.
I'd prefer this check be just warning saying "Rule ignored: register not found". Or something like this.
Hi,
I'm attempting to generate a pac for an nxp rt633s device (svd: https://github.com/nxp-mcuxpresso/mcux-soc-svd/blob/main/MIMXRT633S/MIMXRT633S.xml) however, svd2rust
ends with an error:
[INFO svd2rust] Parsing device from SVD file
[INFO svd2rust] Rendering device
[ERROR svd2rust] Error rendering device
Caused by:
0: Rendering error at peripheral
Name: I2S0
Description: LPC-Next0 I2S interface
Group: I2S
1: Could not expand register or cluster block
2: Error expanding cluster
Name: SECCHANNEL[%s]
Description: no description available
3: Cluster SECCHANNEL[%s] has size 24928 bits that is more then array increment 256 bits
Looking at that particular cluster, we have 96 bits (3x 32-bit registers):
<cluster>
<dim>3</dim>
<dimIncrement>0x20</dimIncrement>
<name>SECCHANNEL[%s]</name>
<description>no description available</description>
<addressOffset>0</addressOffset>
<register>
<name>PCFG1</name>
<description>Configuration register 1 for channel pair</description>
<addressOffset>0xC20</addressOffset>
<size>32</size>
<access>read-write</access>
<resetValue>0</resetValue>
<resetMask>0x401</resetMask>
<fields>
<field>
<name>PAIRENABLE</name>
<description>Enable for this channel pair..</description>
<bitOffset>0</bitOffset>
<bitWidth>1</bitWidth>
<access>read-write</access>
</field>
<field>
<name>ONECHANNEL</name>
<description>Single channel mode.</description>
<bitOffset>10</bitOffset>
<bitWidth>1</bitWidth>
<access>read-write</access>
</field>
</fields>
</register>
<register>
<name>PCFG2</name>
<description>Configuration register 2 for channel pair</description>
<addressOffset>0xC24</addressOffset>
<size>32</size>
<access>read-write</access>
<resetValue>0</resetValue>
<resetMask>0x1FF0000</resetMask>
<fields>
<field>
<name>POSITION</name>
<description>Data Position.</description>
<bitOffset>16</bitOffset>
<bitWidth>9</bitWidth>
<access>read-write</access>
</field>
</fields>
</register>
<register>
<name>PSTAT</name>
<description>Status register for channel pair</description>
<addressOffset>0xC28</addressOffset>
<size>32</size>
<access>read-write</access>
<resetValue>0</resetValue>
<resetMask>0xF</resetMask>
<fields>
<field>
<name>BUSY</name>
<description>Busy status for this channel pair.</description>
<bitOffset>0</bitOffset>
<bitWidth>1</bitWidth>
<access>read-write</access>
</field>
<field>
<name>SLVFRMERR</name>
<description>Save Frame Error flag.</description>
<bitOffset>1</bitOffset>
<bitWidth>1</bitWidth>
<access>read-write</access>
</field>
<field>
<name>LR</name>
<description>Left/Right indication.</description>
<bitOffset>2</bitOffset>
<bitWidth>1</bitWidth>
<access>read-write</access>
</field>
<field>
<name>DATAPAUSED</name>
<description>Data Paused status flag.</description>
<bitOffset>3</bitOffset>
<bitWidth>1</bitWidth>
<access>read-only</access>
</field>
</fields>
</register>
</cluster>
What might be causing the error?
I'm trying to make a patch to clean up the peripherals in the ESP32 USB0 peripheral. It has registers for several endpoints that need to be clustered, and I also want to make some of the registers derive from other registers. svdtools currently doesn't appear to allow me to both apply clustering and make derivedFrom modifications at the same time.
If I add a _derive
section, these changes appear to take be applied before the _cluster
section. When the _derive
changes are made it checks that the derivedFrom register names are valid. However, these register names are later changed by the _cluster
operation, which makes svdtools generate an invalid SVD files since the derivedFrom
fields refer to the old names. I can't use the new names in the _derive
section, since svdtools rejects them as invalid since they don't exist yet when the check is made.
In theory I suppose svdtools should track all derivedFrom
attributes throughout the SVD file, and update them correctly whenever it renames/clusters/derives a register that is the destination of an existing derivedFrom
attribute. This seems possibly more complicated than it is worth, however. Alternatively, it would be nice if there were an easy way to force svdtools to skip the register name check in _derive
, so I could specify the desired derivedFrom
name without svdtools complaining because it doesn't exist yet.
Here is a with more details about what I would like to accomplish
https://github.com/esp-rs/esp-pacs/pull/213/files/e36f054438d1a2a44e81f24eea4efae80ea861e0#r1550642332
I have registers that need to be deleted as follows:
<register>
<dim>2</dim>
<dimIncrement>0x4</dimIncrement>
<name>gpio_set[%s]</name>
<description>Set pin output value to high</description>
<addressOffset>0xAEC</addressOffset>
</register>
However, I attempted to use _delete
without success:
_delete:
gpio_set[%s]:
dim: 35
or
_delete:
gpio_set:
dim: 35
At the same time, I also tried using modify
to make changes, but it didn't work either:
_modify:
gpio_set[%s]:
dim: 35
or
_modify:
gpio_set:
dim: 35
It seems like I cannot select this register. How can I do it?
I'm having problems with the lxml version dependency in the python-svdtools package that maintains the AUR.
...
==> WARNING: Skipping all source file integrity checks.
==> Extracting sources...
-> Extracting svdtools-0.3.9.tar.gz with bsdtar
==> Entering fakeroot environment...
==> Starting package_python-svdtools()...
* Getting build dependencies for wheel...
ERROR Missing dependencies:
lxml~=4.6
==> ERROR: A failure occurred in package_python-svdtools().
Aborting...
...
lxml
relies on the 4.6 version of the package, which is python2-lxml
by checking arch's packages. now arch only supports python3 which requires the python-lxml
package, but the python-lxml
version is 5.2.2. But the python-lxml
version is 5.2.2. It does not meet the dependency requirements of svdtools, please upgrade the lxml version dependency information of svdtools.
yay -Ss python-lxml
...
aur/python2-lxml 4.9.4-2 (+10 0.60)
Python2 binding for the libxml2 and libxslt libraries
blackarch/python2-lxml 4.6.2-2 (1.2 MiB 4.4 MiB)
Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API.
...
extra/python-lxml 5.2.2-1 (1.3 MiB 5.0 MiB) (ๅทฒๅฎ่ฃ
: 5.2.2-1.1)
Python3 binding for the libxml2 and libxslt libraries
extra/python-lxml-docs 5.2.2-1 (3.0 MiB 10.9 MiB)
Python binding for the libxml2 and libxslt libraries (docs)
...
I am writing a peripheral for STM32WLE. One of the bits is best described as "Off", so I wrote:
RRS:
Off: [0, "SRAM2 powered off in Standby mode (SRAM2 content lost)"]
OnLPR: [1, "SRAM2 powered by the low-power regulator in Standby mode (SRAM2 content kept)"]
When running make, I get the following output:
โฏ make
svd makedeps devices/stm32wle5.yaml .deps/stm32wle5.d
svd patch devices/stm32wle5.yaml
Traceback (most recent call last):
File "/Users/xxxx/.pyenv/versions/stm32-rs/bin/svd", line 8, in <module>
sys.exit(svdtools_cli())
File "/Users/xxxx/.pyenv/versions/3.8.9/envs/stm32-rs/lib/python3.8/site-packages/click/core.py", line 1137, in __call__
return self.main(*args, **kwargs)
File "/Users/xxxx/.pyenv/versions/3.8.9/envs/stm32-rs/lib/python3.8/site-packages/click/core.py", line 1062, in main
rv = self.invoke(ctx)
File "/Users/xxxx/.pyenv/versions/3.8.9/envs/stm32-rs/lib/python3.8/site-packages/click/core.py", line 1668, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/Users/xxxx/.pyenv/versions/3.8.9/envs/stm32-rs/lib/python3.8/site-packages/click/core.py", line 1404, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/Users/xxxx/.pyenv/versions/3.8.9/envs/stm32-rs/lib/python3.8/site-packages/click/core.py", line 763, in invoke
return __callback(*args, **kwargs)
File "/Users/xxxx/.pyenv/versions/3.8.9/envs/stm32-rs/lib/python3.8/site-packages/svdtools/cli.py", line 16, in patch
svdtools.patch.main(yaml_file)
File "/Users/xxxx/.pyenv/versions/3.8.9/envs/stm32-rs/lib/python3.8/site-packages/svdtools/patch.py", line 1407, in main
process_device(svd, root)
File "/Users/xxxx/.pyenv/versions/3.8.9/envs/stm32-rs/lib/python3.8/site-packages/svdtools/patch.py", line 1384, in process_device
d.process_peripheral(periphspec, device[periphspec], update_fields)
File "/Users/xxxx/.pyenv/versions/3.8.9/envs/stm32-rs/lib/python3.8/site-packages/svdtools/patch.py", line 661, in process_peripheral
p.process_register(rspec, register, update_fields)
File "/Users/xxxx/.pyenv/versions/3.8.9/envs/stm32-rs/lib/python3.8/site-packages/svdtools/patch.py", line 1032, in process_register
r.process_field(pname, fspec, field)
File "/Users/xxxx/.pyenv/versions/3.8.9/envs/stm32-rs/lib/python3.8/site-packages/svdtools/patch.py", line 1234, in process_field
self.process_field_enum(pname, fspec, field)
File "/Users/xxxx/.pyenv/versions/3.8.9/envs/stm32-rs/lib/python3.8/site-packages/svdtools/patch.py", line 1260, in process_field_enum
enum = make_enumerated_values(name, field, usage=usage)
File "/Users/xxxx/.pyenv/versions/3.8.9/envs/stm32-rs/lib/python3.8/site-packages/svdtools/patch.py", line 148, in make_enumerated_values
if vname.startswith("_"):
AttributeError: 'bool' object has no attribute 'startswith'
make: *** [svd/stm32wle5.svd.patched] Error 1
I am using Python 3.8.9, compiled on x86_64 (I have an M1 so I tried both x86_64 and aarch64).
If instead, I change the bit to:
RRS:
PowerOff: [0, "SRAM2 powered off in Standby mode (SRAM2 content lost)"]
OnLPR: [1, "SRAM2 powered by the low-power regulator in Standby mode (SRAM2 content kept)"]
Everything works normally.
I have tried in other peripherals and bits and the same issue occurs. The same is true if the value is On
, e.g.:
RRS:
PowerOff: [0, "SRAM2 powered off in Standby mode (SRAM2 content lost)"]
On: [1, "SRAM2 powered by the low-power regulator in Standby mode (SRAM2 content kept)"]
to print SVD information and statistics
Regex in derive patch doesnt work
Derive from registers is not documented by the way.
Works correctly:
FLASH:
_derive:
UNLOCK2: UNLOCK
UNLOCK3: UNLOCK
Error:
FLASH:
_derive:
UNLOCK?: UNLOCK
Caused by:
0: Processing device `AT32A403Axx_v2`
1: According to `FLASH`
2: Processing peripheral `FLASH`
3: Deriving register `UNLOCK?` from `String("UNLOCK")`
4: `Build error: `address_offset` must be initialized
5: `address_offset` must be initialized
Ignored:
FLASH:
UNLOCK?:
_derivedFrom: UNLOCK
EXINT:
INTEN:
_array:
INTEN?,INTEN10:
description: "Interrupt enable or disable on line %s"
Token boundaries are calculated without comma split.
svdtools/src/patch/register.rs
Line 361 in 27cf2b1
li = 5, ri = 8
thread 'main' panicked at 'byte index 18446744073709551614 is out of bounds of `INTEN0`', src\patch\register.rs:383:30
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
svdtools/src/patch/register.rs
Line 383 in 27cf2b1
Move and improve the documentation from stm32-rs.
The stm32-rs
crates are depended on by many. Perhaps we should store their outputs with git lfs
or similar, and run regression tests against current last release (or HEAD?) of stm32-rs
?
Currently duplicate keys are silently ignored, which is a common cause of errors.
In principle any conforming YAML parser should emit a warning in such a situation, but PyYAML does not. A workaround might be possible.
Option for svdtools convert
to replace all local derive paths with full paths in register tree.
Related to stm32-rs/stm32-rs#825
There have been votes to rewrite this in Rust, I think most everyone would be open to this, but it would need an external initiative.
How to remove empty fields
tag?
<peripheral>
<name>FLASH</name>
<description>Flash memory controler</description>
<groupName>FLASH</groupName>
<registers>
<register>
<name>PSR</name>
<displayName>PSR</displayName>
<description>Performance selection register</description>
<addressOffset>0x0</addressOffset>
<size>0x20</size>
<resetValue>0x00000030</resetValue>
<fields>
</fields>
</register>
</registers>
</peripheral>
The current behavior of _strip_end will trim the input string to the length of the substring targeted for removal.
For example:
a patch to _strip_end "_REG" from all register names, with the register name IO_MUX_GPIO36_REG will result in IO_M
The conditional to determine whether a name should be stripped on the front or back is also not behaving as intended. If the function is called to strip the end, and doesn't strip the end, it will then try to strip the front. For example, with the previous patch _strip_end "_REG", "_REG_IO_MUX" would become "_IO_MUX".
Letโs say we have some peripheral that exposes an interface to feed it with some 128-bit inputs (letโs say 3 for the example), and we have a 32-bit bus. It then provides registers like: INPUT0A
, INPUT0B
, INPUT0C
, INPUT0D
, INPUT1A
, ..., INPUT3D
. INPUT0A
is the first 32-bit word in input 0, INPUT3B
the second 32-bit word in input 3, and so on.
As you can imagine, working with such registers in a generic way in the code is not very handy, so Iโd like to group them in some kind of two-dimentional array, like INPUT[n][w]
, where n
is the input number and w
the 32-bit word index inside this 128-bit input.
svdtools
The first step Iโve done is to create arrays for each input, like:
PERIPHERAL:
_array:
INPUT0?: {}
INPUT1?: {}
INPUT2?: {}
This is better since I can now do in my Rust code:
peripheral.input0[w].write(|w| ...);
// ...
peripheral.input1[w].write(|w| ...);
There is still however a hard-coded index in the names, so I need to use macros to get generic code, which is not optimal.
While looking to the SVD documentation, I came to see that we can put registers in clusters, and we can do arrays of clusters. I can then write something like:
<cluster>
<dim>3</dim>
<dimIncrement>0x10</dimIncrement>
<dimIndex>0-2</dimIndex>
<name>INPUT%s</name>
<description>Input registers</description>
<addressOffset>0x100</addressOffset>
<register>
<dim>4</dim>
<dimIncrement>0x04</dimIncrement>
<dimIndex>0-3</dimIndex>
<name>WORD%s</name>
<description>Word</description>
<addressOffset>0x0</addressOffset>
<size>32</size>
<access>read-write</access>
<resetValue>0x0</resetValue>
<resetMask>0xFFFFFFFF</resetMask>
<fields>
<field>
<name>WORD</name>
<description>Word</description>
<bitOffset>0</bitOffset>
<bitWidth>32</bitWidth>
<access>read-write</access>
</field>
</fields>
</register>
</cluster>
This allows me to write Rust code like:
peripheral.input[n].word[w].write(|w| ...);
which is exactly what I want.
svdtools
?Is it possible to achieve this with svdtools
? I see two possible paths:
_add
clusters and arrays? (Actually the original SVD Iโm using has the registers for only 1 input, so Iโd be fine to just define them from scratch in a _add
block)ARM (and others, I assume) provide a number of ready-to-use IP blocks which chip manufacturers
can use. Examples include the SP804 dual timer, SP805 watchdog, PL390 GIC, PL080 DMAC, PL011
UART, and so on.
It could be useful to provide a collection of these 'standard parts' in a library for use in patching
and creating svds.
TL;DR: most svdtools features don't work within the <cluster>
tag. Should they?
Somewhat similar to #27, our platform SVDs have registers organized into clusters like so:
<peripheral>
<name>SUBSYSTEM</name>
<cluster>
<name>PERIPHERAL_1</name>
<description />
<register>REG_1</register>
<register>REG_2.</register>
</cluster>
<cluster>
<name>PERIPHERAL_2name>
<description />
<register>...</register>
<register>...</register>
</cluster>
</peripheral>
I have no idea whether it's a good idea to arrange the device like so but in case one does, we encounter issues with svd patch
which seems to be unable to make most types of changes inside clusters.
Take for instance _array
. If you were to write the following patch.yaml against the above architecture:
"SUBSYSTEM":
_array:
REG_*: {}
you would get the following error:
File "src/lxml/etree.pyx", line 943, in lxml.etree._Element.remove
ValueError: Element is not a child of this node.
while if you didn't have the cluster layer, the operation would pass successfully. I suspect the svd patch
code is looking for the matching "REG_*" symbols as leaf of the <peripheral>SUBSYSTEM</peripheral>
-layer, while they cannot be found due to the symbols actually being wrapped one layer deeper inside a <cluster>
-tag. However, we cannot currently represent the cluster-layer in the YAML syntax. #27 seems to work around this through clever re-use of _cluster
tag.
Did I get the problem statement right? How do you feel about the issue? Do you think it's a user problem i.e. too weird SVD layout, or would it be appropriate for svd patch
to support changes inside clusters.
If you think this is in the "should fix" category, I could investigate if I could come up with a PR for it. In that case I'd need at least an opinion on if the cluster-layer could be represented in the YAML patch syntax similar to the peripheral, register and field layers, like so:
"PERIPHERAL":
CLUSTER:
REGISTER:
_modify:
FIELD:
description: "a description"
Ello. I'm using the rust svdtools program to build an svd for a chip without one.
I started by converting the rp2040.svd to rp2040.yaml as a reference, and began
writing the yaml for my chip, to convert to svd later for use with gdb and such.
Some of the data is dummied out (for instance, its not a traditional mcu, but is
a cortex-a7 proc). Attempting to convert with what I currently have (below) results
in the following error:
[2022-04-11T13:49:24Z ERROR svdtools::cli] peripherals[0]: invalid type: map, expected a sequence at line 20 column 9
Line 20 column 9 translates to the :
before BOOT_ADDR; this seems correct,
as the rp2040.yaml file has the same kind of setup:
Am I missing something or is this a legit bug?
---
vendor: Raspberry Pi
name: RP2040
version: "0.1"
description: ""
licenseText: "\n Copyright (c) 2020 Raspberry Pi (Trading) Ltd. \\n\n \\n\n SPDX-License-Identifier: BSD-3-Clause\n "
cpu:
name: CM0PLUS
revision: r0p1
endian: little
mpuPresent: true
fpuPresent: false
vtorPresent: true
nvicPrioBits: 2
vendorSystickConfig: false
deviceNumInterrupts: 26
addressUnitBits: 8
width: 32
peripherals:
- name: XIP_CTRL
---
vendor: Hisilicon
name: Hi3521A
version: "0.0"
description: ""
licenseText: ""
cpu:
name: other
revision: r0p1
endian: little
mpuPresent: true
fpuPresent: true
vtorPresent: true
nvicPrioBits: 0
vendorSystickConfig: false
deviceNumInterrupts: 64
addressUnitBits: 8
width: 32
peripherals:
- name: BOOT_ADDR
version: "1"
description: ""
baseAddress: 0x0
size: 32
addressBlock:
offset: 0
size: 0x4000000
usage: buffer
- name: BOOT_ROM
version: "1"
description: ""
baseAddress: 0x04000000
size: 32
addressBlock:
offset: 0
size: 0x1000
usage: buffer
- name: SRAM
version: "1"
description: ""
baseAddress: 0x04010000
size: 32
addressBlock:
offset: 0
size: 0x4000
usage: buffer
- name: FMC_CTRL
version: "1"
description: ""
baseAddress: 0x10000000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: OHCI
version: "1"
description: ""
baseAddress: 0x10030000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: EHCI
version: "1"
description: ""
baseAddress: 0x10040000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: DMAC
version: "1"
description: ""
baseAddress: 0x10060000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: CIPHER
version: "1"
description: ""
baseAddress: 0x10070000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: SCD
version: "1"
description: ""
baseAddress: 0x10080000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: GSF
version: "1"
description: ""
baseAddress: 0x100a0000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: SATA
version: "1"
description: ""
baseAddress: 0x11010000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: TIMER01
version: "1"
description: ""
baseAddress: 0x12000000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: TIMER23
version: "1"
description: ""
baseAddress: 0x12010000
size: 32
- name: TIMER45
version: "1"
description: ""
baseAddress: 0x12020000
size: 32
- name: TIMER67
version: "1"
description: ""
baseAddress: 0x12030000
size: 32
- name: CRG
version: "1"
description: ""
baseAddress: 0x12040000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
registers:
- register:
name: CRG_PLL0
description: APLL configuration register 0
addressOffset: 0x0000
resetValue: 0x12000000
fields:
- name: postdiv2
description: Level-2 output divider of the APLL
bitRange: "[30:28]"
access: read-write
- name: postdiv1
description: Level-1 output divider of the APLL
bitRange: "[26:24]"
access: read-write
- name: frac
description: Decimal divider of the APLL
bitRange: "[23:0]"
access: read-write
name: CRG_PLL1
description: APLL configuration register 0
addressOffset: 0x0004
resetValue: 0x02003064
fields:
- name: bypass
description: APLL clock frequency-division bypass control
bitRange: "[26:26]"
access: read-write
- name: dacpd
description: APLL test signal control
bitRange: "[25:25]"
access: read-write
- name: dsmpd
description: APLL decimal frequency-division control
bitRange: "[24:24]"
access: read-write
- name: pd
description: PLL power-down control
bitRange: "[23:23]"
access: read-write
- name: foutvcopd
description: Power-down control for the APLL VCO output
bitRange: "[22:22]"
access: read-write
- name: postdivpd
description: Power-down control for the APLL POSTDIV output
bitRange: "[21:21]"
access: read-write
- name: fout4phasepd
description: Power-down control for the APLL FOUT output
bitRange: "[20:20]"
access: read-write
- name: refdiv
description: Divider of the APLL reference clock
bitRange: "[17:12]"
access: read-write
- name: fbdiv
description: Integral multiplier of the APLL
bitRange: "[11:0]"
access: read-write
- name: SYSCTL
version: "1"
description: ""
baseAddress: 0x12050000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: WDG
version: "1"
description: ""
baseAddress: 0x12070000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: UART0
version: "1"
description: ""
baseAddress: 0x12080000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: UART1
version: "1"
description: ""
baseAddress: 0x12090000
size: 32
- name: UART2
version: "1"
description: ""
baseAddress: 0x120a0000
size: 32
- name: RTC
version: "1"
description: ""
baseAddress: 0x120b0000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: I2C
version: "1"
description: ""
baseAddress: 0x120c0000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: SSP
version: "1"
description: ""
baseAddress: 0x120d0000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: PMC
version: "1"
description: ""
baseAddress: 0x120e0000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: PINMUX
version: "1"
description: ""
baseAddress: 0x120f0000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: PINCTRL
version: "1"
description: ""
baseAddress: 0x120f0800
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: DDRT0
version: "1"
description: ""
baseAddress: 0x12100000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: DDRC
version: "1"
description: ""
baseAddress: 0x12110000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: PERICTL
version: "1"
description: ""
baseAddress: 0x12120000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: IR
version: "1"
description: ""
baseAddress: 0x12140000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: GPIO00
version: "1"
description: ""
baseAddress: 0x12150000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: GPIO01
version: "1"
description: ""
baseAddress: 0x12160000
size: 32
- name: GPIO02
version: "1"
description: ""
baseAddress: 0x12170000
size: 32
- name: GPIO03
version: "1"
description: ""
baseAddress: 0x12180000
size: 32
- name: GPIO04
version: "1"
description: ""
baseAddress: 0x12190000
size: 32
- name: GPIO05
version: "1"
description: ""
baseAddress: 0x121a0000
size: 32
- name: GPIO06
version: "1"
description: ""
baseAddress: 0x121b0000
size: 32
- name: GPIO07
version: "1"
description: ""
baseAddress: 0x121c0000
size: 32
- name: GPIO08
version: "1"
description: ""
baseAddress: 0x121d0000
size: 32
- name: GPIO09
version: "1"
description: ""
baseAddress: 0x121e0000
size: 32
- name: GPIO10
version: "1"
description: ""
baseAddress: 0x121f0000
size: 32
- name: GPIO11
version: "1"
description: ""
baseAddress: 0x12200000
- name: GPIO12
version: "1"
description: ""
baseAddress: 0x12210000
- name: GPIO13
version: "1"
description: ""
baseAddress: 0x12220000
- name: HDMI
version: "1"
description: ""
baseAddress: 0x13010000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: VDP
version: "1"
description: ""
baseAddress: 0x13020000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: AVC0
version: "1"
description: ""
baseAddress: 0x13040000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: TDE
version: "1"
description: ""
baseAddress: 0x13050000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: IVE
version: "1"
description: ""
baseAddress: 0x13060000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: JPGD
version: "1"
description: ""
baseAddress: 0x13070000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: VGS
version: "1"
description: ""
baseAddress: 0x13080000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: VICAP
version: "1"
description: ""
baseAddress: 0x130c0000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: AVC1
version: "1"
description: ""
baseAddress: 0x13100000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: VPSS
version: "1"
description: ""
baseAddress: 0x13110000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: VOIE
version: "1"
description: ""
baseAddress: 0x13120000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: JPGE
version: "1"
description: ""
baseAddress: 0x13130000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: AIAO
version: "1"
description: ""
baseAddress: 0x13140000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: MDU
version: "1"
description: ""
baseAddress: 0x13150000
size: 32
addressBlock:
offset: 0
size: 0x10000
usage: registers
- name: SFC_MEM
version: "1"
description: ""
baseAddress: 0x14000000
size: 32
addressBlock:
offset: 0
size: 0x1000000
usage: buffer
- name: DRAM
version: "1"
description: ""
baseAddress: 0x80000000
size: 32
addressBlock:
offset: 0
size: 0x80000000
usage: buffer
As far as I can tell, there is no way to use the svd patch tool to add a derivedFrom
attribute to an enumeratedValues
tag. This should be possible. I would like to do this so that svd2rust
uses the same enum type for the equivalent field on several different peripherals. I would expect to be able to do something like
TIMER2:
CHCTL2:
_derive:
CH0P: TIMER0.CHCTL2.CH0P
Or perhaps:
TIMER2:
CHCTL2:
_modify:
CH0P:
derivedFrom: TIMER0.CHCTL2.CH0P
But neither of these seem to work at the moment.
Example:
PADS_QSPI:
_delete:
"VOLTAGE_SELECT":
_derive:
"VOLTAGE_SELECT":
_from: "PADS_BANK0.VOLTAGE_SELECT"
fails with svdtools.patch.SvdPatchError: register PADS_BANK0.VOLTAGE_SELECT not found
Could be related to def derive_from
searching for the target register in the parent only rather than decomposing the target register's name.
So, I know this is mostly used to patch vendor-shipped svd files, but as prior issues have stated,
I've been using this to write svd's for cortex-a socs in yaml for use in other projects (ghidra, pycortexmdebug,
etc).
Is it possible, for example, do do the patching type stuff without a 'real' 'seed' svd file?
Like, I'd want to define all the svd blocks for stuff that is unique to this particular soc (clock controllers,
system controllers, various glue peripherals) in the primary yaml file, and draw from various 'library'
yaml files that define 'standard' peripherals (arm primecell stuff, designware stuff, etc).
I realize I can just concatenate main.yaml, gpioX.yaml, and so on, but that gets awkward as time goes on
and the file grows.
For example, one could have a file tree like this:
.
โโโ hi3516dv300.yaml
โโโ hi3521av100.yaml
โโโ peripherals
โโโ designware
โย ย โโโ dw-mmc.yaml
โโโ primecell
โโโ pl011.yaml
โโโ pl061.yaml
โโโ sp804.yaml
Where hi3516dv300.yaml defines that there is a pl061 gpio at every 0x120d_{0..b}000
address block but
hi3521av100 has them at 0x12{15..22}_0000
and so on?
My svd has a peripheral PWM with a cluster SM and register SMOCTRL
In 0.2.8 I could patch fields in SMOCTRL with...
PWM?:
SMOCTRL:
_clear:
- PWMXFS
- PWMBFS
- PWMAFS
With 0.3.6 it can't find the SWOCTRL register and its unclear to me how to select it (in the cluster SM)
Actual yaml patch
https://github.com/imxrt-rs/imxrt-ral/blob/master/devices/imxrt1176_cm7.yaml#L105
Actual SVD
https://github.com/imxrt-rs/imxrt-ral/blob/master/svd/imxrt1176_cm7.svd
When running svdpatch against register with modified base address written as number I get the following error:
Traceback (most recent call last):
File "scripts/svdpatch.py", line 883, in <module>
main()
File "scripts/svdpatch.py", line 876, in main
process_device(svd, root)
File "scripts/svdpatch.py", line 855, in process_device
update_fields)
File "scripts/svdpatch.py", line 400, in process_peripheral
p.collect_in_array(rspec, rmod)
File "scripts/svdpatch.py", line 511, in collect_in_array
int(rtag.findtext('addressOffset'), 0)])
TypeError: int() can't convert non-string with explicit base
Makefile:38: recipe for target 'svd/stm32f427.svd.patched' failed
make: *** [svd/stm32f427.svd.patched] Error 1
Input used to generate this error:
OTG_HS_GLOBAL:
_modify:
DIEPTXF3:
addressOffset: 0x10C
_array:
DIEPTXF[12345]: {}
If I put the address in quotes like this: addressOffset: 0x10C
everything works fine.
#106 added support for modifiedWriteValues but this ignored in patches
SCR:
_modify:
IOSB0:
access: write-only
modifiedWriteValues: oneToClear
<field>
<name>IOSB0</name>
<description>Set bit 0</description>
<bitOffset>0</bitOffset>
<bitWidth>1</bitWidth>
<access>write-only</access> << it works
</field>
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.