merge main and resolve conflict

This commit is contained in:
Pierre Constantineau 2021-12-10 16:57:50 -06:00
commit 86ddecfd4f
521 changed files with 13680 additions and 906 deletions

View File

@ -20,6 +20,7 @@ jobs:
boards-arm: ${{ steps.set-matrix.outputs.boards-arm }}
boards-riscv: ${{ steps.set-matrix.outputs.boards-riscv }}
boards-espressif: ${{ steps.set-matrix.outputs.boards-espressif }}
boards-aarch: ${{ steps.set-matrix.outputs.boards-aarch }}
steps:
- name: Dump GitHub context
env:
@ -28,19 +29,17 @@ jobs:
- uses: actions/checkout@v2.2.0
with:
submodules: false
fetch-depth: 0
- name: Populate selected submodules
run: git submodule update --init extmod/ lib/ tools/
- name: Fetch tags
run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
- name: CircuitPython version
run: |
git describe --dirty --tags
echo >>$GITHUB_ENV CP_VERSION=$(git describe --dirty --tags)
fetch-depth: 1
- name: Set up Python 3.8
uses: actions/setup-python@v1
with:
python-version: 3.8
- name: Get CP deps
run: python tools/ci_fetch_deps.py test ${{ github.sha }}
- name: CircuitPython version
run: |
git describe --dirty --tags || git log --parents HEAD~4..
echo >>$GITHUB_ENV CP_VERSION=$(git describe --dirty --tags)
- name: Install dependencies
run: |
sudo apt-get update
@ -136,19 +135,17 @@ jobs:
- uses: actions/checkout@v2.2.0
with:
submodules: false
fetch-depth: 0
- name: Populate selected submodules
run: git submodule update --init extmod/ lib/ tools/
- name: Fetch tags
run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
- name: CircuitPython version
run: |
git describe --dirty --tags
echo >>$GITHUB_ENV CP_VERSION=$(git describe --dirty --tags)
fetch-depth: 1
- name: Set up Python 3.8
uses: actions/setup-python@v1
with:
python-version: 3.8
- name: Get CP deps
run: python tools/ci_fetch_deps.py mpy-cross-mac ${{ github.sha }}
- name: CircuitPython version
run: |
git describe --dirty --tags
echo >>$GITHUB_ENV CP_VERSION=$(git describe --dirty --tags)
- name: Install dependencies
run: |
brew install gettext
@ -198,11 +195,9 @@ jobs:
- uses: actions/checkout@v2.2.0
with:
submodules: false
fetch-depth: 0
- name: Populate selected submodules
run: git submodule update --init extmod/
- name: Fetch tags
run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
fetch-depth: 1
- name: Get CP deps
run: python tools/ci_fetch_deps.py docs ${{ github.sha }}
- name: CircuitPython version
run: |
git describe --dirty --tags
@ -271,10 +266,10 @@ jobs:
python-version: 3.8
- uses: actions/checkout@v2.2.0
with:
submodules: true
fetch-depth: 0
- name: Fetch tags
run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
submodules: false
fetch-depth: 1
- name: Get CP deps
run: python tools/ci_fetch_deps.py ${{ matrix.board }} ${{ github.sha }}
- name: Install dependencies
run: |
sudo apt-get install -y gettext
@ -323,10 +318,10 @@ jobs:
python-version: 3.8
- uses: actions/checkout@v2.2.0
with:
submodules: true
fetch-depth: 0
- name: Fetch tags
run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
submodules: false
fetch-depth: 1
- name: Get CP deps
run: python tools/ci_fetch_deps.py ${{ matrix.board }} ${{ github.sha }}
- name: Install dependencies
run: |
sudo apt-get install -y gettext
@ -375,10 +370,10 @@ jobs:
python-version: 3.8
- uses: actions/checkout@v2.2.0
with:
submodules: true
fetch-depth: 0
- name: Fetch tags
run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
submodules: false
fetch-depth: 1
- name: Get CP deps
run: python tools/ci_fetch_deps.py ${{ matrix.board }} ${{ github.sha }}
- name: CircuitPython version
run: git describe --dirty --tags
- uses: actions/cache@v2
@ -446,3 +441,67 @@ jobs:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
if: (github.event_name == 'push' && github.ref == 'refs/heads/main' && github.repository_owner == 'adafruit') || (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested'))
build-aarch:
runs-on: ubuntu-20.04
needs: test
strategy:
fail-fast: false
matrix:
board: ${{ fromJSON(needs.test.outputs.boards-aarch) }}
if: ${{ needs.test.outputs.boards-aarch != '[]' }}
steps:
- name: Set up Python 3.8
uses: actions/setup-python@v1
with:
python-version: 3.8
- uses: actions/checkout@v2.2.0
with:
submodules: false
fetch-depth: 1
- name: Get CP deps
run: python tools/ci_fetch_deps.py ${{ matrix.board }} ${{ github.sha }}
- name: Install dependencies
run: |
sudo apt-get install -y gettext mtools
pip install -r requirements-ci.txt -r requirements-dev.txt
wget --no-verbose https://adafruit-circuit-python.s3.amazonaws.com/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz
sudo tar -C /usr --strip-components=1 -xaf gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz
wget --no-verbose https://adafruit-circuit-python.s3.amazonaws.com/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
sudo tar -C /usr --strip-components=1 -xaf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
- name: Install mkfs.fat
run: |
wget https://github.com/dosfstools/dosfstools/releases/download/v4.2/dosfstools-4.2.tar.gz
tar -xaf dosfstools-4.2.tar.gz
cd dosfstools-4.2
./configure
make -j 2
cd src
echo >>$GITHUB_PATH $(pwd)
- name: Versions
run: |
gcc --version
aarch64-none-elf-gcc --version
arm-none-eabi-gcc --version
python3 --version
mkfs.fat --version || true
- name: mpy-cross
run: make -C mpy-cross -j2
- name: Setup build failure matcher
run: echo "::add-matcher::$GITHUB_WORKSPACE/.github/workflows/match-build-fail.json"
- name: build
run: python3 -u build_release_files.py
working-directory: tools
env:
BOARDS: ${{ matrix.board }}
- uses: actions/upload-artifact@v2
with:
name: ${{ matrix.board }}
path: bin/${{ matrix.board }}
- name: Upload to S3
run: "[ -z \"$AWS_ACCESS_KEY_ID\" ] || aws s3 cp bin/ s3://adafruit-circuit-python/bin/ --recursive --no-progress --region us-east-1"
env:
AWS_PAGER: ''
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
if: (github.event_name == 'push' && github.ref == 'refs/heads/main' && github.repository_owner == 'adafruit') || (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested'))

View File

@ -18,12 +18,14 @@ jobs:
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2.2.0
with:
submodules: true
fetch-depth: 0
submodules: false
fetch-depth: 1
- name: Set up Python 3.8
uses: actions/setup-python@v1
with:
python-version: 3.8
- name: Get CP deps
run: python tools/ci_fetch_deps.py website ${{ github.sha }}
- name: Install deps
run: |
pip install -r requirements-dev.txt
@ -31,7 +33,6 @@ jobs:
run: |
gcc --version
python3 --version
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
- name: CircuitPython version
run: git describe --dirty --tags
- name: Website

14
.github/workflows/notify.yml vendored Normal file
View File

@ -0,0 +1,14 @@
name: Notify users based on issue labels
on:
issues:
types: [labeled]
jobs:
notify:
runs-on: ubuntu-latest
steps:
- uses: jenschelkopf/issue-label-notification-action@1.3
with:
recipients: |
ulab=@v923z

View File

@ -65,12 +65,12 @@ jobs:
which python; python --version; python -c "import cascadetoml"
which python3; python3 --version; python3 -c "import cascadetoml"
- uses: actions/checkout@v2
- uses: actions/checkout@v2.2.0
with:
submodules: true
fetch-depth: 0
- run: git fetch --recurse-submodules=no https://github.com/adafruit/circuitpython refs/tags/*:refs/tags/*
submodules: false
fetch-depth: 1
- name: Get CP deps
run: python tools/ci_fetch_deps.py windows ${{ github.sha }}
- name: CircuitPython version
run: |
git describe --dirty --tags

View File

@ -12,7 +12,7 @@ jobs:
pre-commit:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2.2.0
- uses: actions/setup-python@v1
- name: Install deps
run: |

13
.gitmodules vendored
View File

@ -109,7 +109,7 @@
url = https://github.com/adafruit/Adafruit_CircuitPython_Register.git
[submodule "extmod/ulab"]
path = extmod/ulab
url = https://github.com/adafruit/circuitpython-ulab
url = https://github.com/v923z/micropython-ulab
[submodule "frozen/Adafruit_CircuitPython_ESP32SPI"]
path = frozen/Adafruit_CircuitPython_ESP32SPI
url = https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI
@ -149,7 +149,7 @@
[submodule "ports/espressif/esp-idf"]
path = ports/espressif/esp-idf
url = https://github.com/espressif/esp-idf.git
branch = release/v4.3
branch = release/v4.4
[submodule "ports/espressif/certificates/nina-fw"]
path = ports/espressif/certificates/nina-fw
url = https://github.com/adafruit/nina-fw.git
@ -190,3 +190,12 @@
[submodule "frozen/Adafruit_CircuitPython_APDS9960"]
path = frozen/Adafruit_CircuitPython_APDS9960
url = https://github.com/adafruit/Adafruit_CircuitPython_APDS9960
[submodule "ports/broadcom/peripherals"]
path = ports/broadcom/peripherals
url = https://github.com/adafruit/broadcom-peripherals.git
branch = main-build
[submodule "rpi-firmware"]
path = ports/broadcom/firmware
url = https://github.com/raspberrypi/rpi-firmware.git
branch = master
shallow = true

View File

@ -321,3 +321,11 @@ clean-nrf:
clean-stm:
$(MAKE) -C ports/stm BOARD=feather_stm32f405_express clean
.PHONY: fetch-submodules
fetch-submodules:
# This update will fail because the commits we need aren't the latest on the
# branch. We can ignore that though because we fix it with the second command.
# (Only works for git servers that allow sha fetches.)
git submodule update --init -N --depth 1 || true
git submodule foreach 'git fetch --tags --depth 1 origin $$sha1 && git checkout -q $$sha1'

View File

@ -213,7 +213,7 @@ Supported Support status
================ ============================================================
atmel-samd ``SAMD21`` stable | ``SAMD51`` stable
cxd56 stable
espressif ``ESP32-C3`` beta | ``ESP32-S2`` stable
espressif ``ESP32-C3`` beta | ``ESP32-S2`` stable | ``ESP32-S3`` beta
litex alpha
mimxrt10xx alpha
nrf stable
@ -229,7 +229,7 @@ unix alpha
Boards
~~~~~~
- Each ``port`` has a ``boards`` directory containing variations of boards
- Each ``port`` has a ``boards`` directory containing boards
which belong to a specific microcontroller line.
- A list of native modules supported by a particular board can be found
`here <https://circuitpython.readthedocs.io/en/latest/shared-bindings/support_matrix.html>`__.

View File

@ -186,6 +186,8 @@ exclude_patterns = ["**/build*",
"ports/atmel-samd/peripherals",
"ports/atmel-samd/QTouch",
"ports/atmel-samd/tools",
"ports/broadcom/firmware",
"ports/broadcom/peripherals",
"ports/cxd56/mkspk",
"ports/cxd56/spresense-exported-sdk",
"ports/espressif/certificates",

@ -1 +1 @@
Subproject commit e5b149599d14a8841167fe552846ca36925b87a0
Subproject commit 266ea20ed80104c315dcb124b482fa5f9f48cdec

View File

@ -938,8 +938,8 @@ uint16_t bleio_adapter_max_attribute_handle(bleio_adapter_obj_t *adapter) {
void bleio_adapter_gc_collect(bleio_adapter_obj_t *adapter) {
gc_collect_root((void **)adapter, sizeof(bleio_adapter_obj_t) / sizeof(size_t));
gc_collect_root((void **)bleio_connections, sizeof(bleio_connections) / sizeof(size_t));
gc_collect_root((void **)adapter, sizeof(bleio_adapter_obj_t) / (sizeof(size_t)));
gc_collect_root((void **)bleio_connections, sizeof(bleio_connections) / (sizeof(size_t)));
}
void bleio_adapter_reset(bleio_adapter_obj_t *adapter) {

View File

@ -107,6 +107,6 @@ void common_hal_bleio_gc_collect(void) {
}
void bleio_background(void) {
void bleio_hci_background(void) {
bleio_adapter_background(&common_hal_bleio_adapter_obj);
}

View File

@ -34,7 +34,7 @@
#include "att.h"
#include "hci.h"
void bleio_background(void);
void bleio_hci_background(void);
void bleio_reset(void);
typedef struct {

View File

@ -30,7 +30,7 @@ import sys
from concurrent.futures import ThreadPoolExecutor
SUPPORTED_PORTS = ['atmel-samd', 'cxd56', 'espressif', 'litex', 'mimxrt10xx', 'nrf', 'raspberrypi', 'stm']
SUPPORTED_PORTS = ['atmel-samd', 'broadcom', 'cxd56', 'espressif', 'litex', 'mimxrt10xx', 'nrf', 'raspberrypi', 'stm']
aliases_by_board = {
"circuitplayground_express": [

@ -1 +1 @@
Subproject commit b913d064e525f674d0219524988e6d9d834fe09c
Subproject commit c03990cc56283417e752246c2738199f65d1b7ef

View File

@ -440,7 +440,7 @@ STATIC const mp_obj_property_t fat_vfs_label_obj = {
.base.type = &mp_type_property,
.proxy = {(mp_obj_t)&fat_vfs_getlabel_obj,
(mp_obj_t)&fat_vfs_setlabel_obj,
MP_ROM_NONE},
(mp_obj_t)MP_ROM_NONE},
};
#endif

@ -1 +1 @@
Subproject commit 2c89a329063848bcd7dba6af6fb6c9d6036dd4f2
Subproject commit 3bdd335452ff14a53d1e840de043e3159cb3b829

View File

@ -1985,7 +1985,7 @@ static void gen_numname (
if (c > '9') c += 7;
ns[i--] = c;
seq /= 16;
} while (seq);
} while (seq && i > 0);
ns[i] = '~';
/* Append the number to the SFN body */

9
lib/sdmmc/CMakeLists.txt Normal file
View File

@ -0,0 +1,9 @@
idf_component_register(SRCS "sdmmc_cmd.c"
"sdmmc_common.c"
"sdmmc_init.c"
"sdmmc_io.c"
"sdmmc_mmc.c"
"sdmmc_sd.c"
INCLUDE_DIRS include
REQUIRES driver
PRIV_REQUIRES soc)

0
lib/sdmmc/component.mk Normal file
View File

View File

@ -0,0 +1,274 @@
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <stdio.h>
#include "sdmmc_defs.h"
#include "sdmmc_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Probe and initialize SD/MMC card using given host
*
* @note Only SD cards (SDSC and SDHC/SDXC) are supported now.
* Support for MMC/eMMC cards will be added later.
*
* @param host pointer to structure defining host controller
* @param out_card pointer to structure which will receive information
* about the card when the function completes
* @return
* - SDMMC_OK on success
* - One of the error codes from SDMMC host controller
*/
sdmmc_err_t sdmmc_card_init(const sdmmc_host_t* host,
sdmmc_card_t* out_card);
/**
* @brief Print information about the card to a stream
* @param stream stream obtained using fopen or fdopen
* @param card card information structure initialized using sdmmc_card_init
*/
void sdmmc_card_print_info(FILE* stream, const sdmmc_card_t* card);
/**
* Write given number of sectors to SD/MMC card
*
* @param card pointer to card information structure previously initialized
* using sdmmc_card_init
* @param src pointer to data buffer to read data from; data size must be
* equal to sector_count * card->csd.sector_size
* @param start_sector sector where to start writing
* @param sector_count number of sectors to write
* @return
* - SDMMC_OK on success
* - One of the error codes from SDMMC host controller
*/
sdmmc_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src,
size_t start_sector, size_t sector_count);
/**
* Read given number of sectors from the SD/MMC card
*
* @param card pointer to card information structure previously initialized
* using sdmmc_card_init
* @param dst pointer to data buffer to write into; buffer size must be
* at least sector_count * card->csd.sector_size
* @param start_sector sector where to start reading
* @param sector_count number of sectors to read
* @return
* - SDMMC_OK on success
* - One of the error codes from SDMMC host controller
*/
sdmmc_err_t sdmmc_read_sectors(sdmmc_card_t* card, void* dst,
size_t start_sector, size_t sector_count);
/**
* Read one byte from an SDIO card using IO_RW_DIRECT (CMD52)
*
* @param card pointer to card information structure previously initialized
* using sdmmc_card_init
* @param function IO function number
* @param reg byte address within IO function
* @param[out] out_byte output, receives the value read from the card
* @return
* - SDMMC_OK on success
* - One of the error codes from SDMMC host controller
*/
sdmmc_err_t sdmmc_io_read_byte(sdmmc_card_t* card, uint32_t function,
uint32_t reg, uint8_t *out_byte);
/**
* Write one byte to an SDIO card using IO_RW_DIRECT (CMD52)
*
* @param card pointer to card information structure previously initialized
* using sdmmc_card_init
* @param function IO function number
* @param reg byte address within IO function
* @param in_byte value to be written
* @param[out] out_byte if not NULL, receives new byte value read
* from the card (read-after-write).
* @return
* - SDMMC_OK on success
* - One of the error codes from SDMMC host controller
*/
sdmmc_err_t sdmmc_io_write_byte(sdmmc_card_t* card, uint32_t function,
uint32_t reg, uint8_t in_byte, uint8_t* out_byte);
/**
* Read multiple bytes from an SDIO card using IO_RW_EXTENDED (CMD53)
*
* This function performs read operation using CMD53 in byte mode.
* For block mode, see sdmmc_io_read_blocks.
*
* @param card pointer to card information structure previously initialized
* using sdmmc_card_init
* @param function IO function number
* @param addr byte address within IO function where reading starts
* @param dst buffer which receives the data read from card
* @param size number of bytes to read
* @return
* - SDMMC_OK on success
* - SDMMC_ERR_INVALID_SIZE if size exceeds 512 bytes
* - One of the error codes from SDMMC host controller
*/
sdmmc_err_t sdmmc_io_read_bytes(sdmmc_card_t* card, uint32_t function,
uint32_t addr, void* dst, size_t size);
/**
* Write multiple bytes to an SDIO card using IO_RW_EXTENDED (CMD53)
*
* This function performs write operation using CMD53 in byte mode.
* For block mode, see sdmmc_io_write_blocks.
*
* @param card pointer to card information structure previously initialized
* using sdmmc_card_init
* @param function IO function number
* @param addr byte address within IO function where writing starts
* @param src data to be written
* @param size number of bytes to write
* @return
* - SDMMC_OK on success
* - SDMMC_ERR_INVALID_SIZE if size exceeds 512 bytes
* - One of the error codes from SDMMC host controller
*/
sdmmc_err_t sdmmc_io_write_bytes(sdmmc_card_t* card, uint32_t function,
uint32_t addr, const void* src, size_t size);
/**
* Read blocks of data from an SDIO card using IO_RW_EXTENDED (CMD53)
*
* This function performs read operation using CMD53 in block mode.
* For byte mode, see sdmmc_io_read_bytes.
*
* @param card pointer to card information structure previously initialized
* using sdmmc_card_init
* @param function IO function number
* @param addr byte address within IO function where writing starts
* @param dst buffer which receives the data read from card
* @param size number of bytes to read, must be divisible by the card block
* size.
* @return
* - SDMMC_OK on success
* - SDMMC_ERR_INVALID_SIZE if size is not divisible by 512 bytes
* - One of the error codes from SDMMC host controller
*/
sdmmc_err_t sdmmc_io_read_blocks(sdmmc_card_t* card, uint32_t function,
uint32_t addr, void* dst, size_t size);
/**
* Write blocks of data to an SDIO card using IO_RW_EXTENDED (CMD53)
*
* This function performs write operation using CMD53 in block mode.
* For byte mode, see sdmmc_io_write_bytes.
*
* @param card pointer to card information structure previously initialized
* using sdmmc_card_init
* @param function IO function number
* @param addr byte address within IO function where writing starts
* @param src data to be written
* @param size number of bytes to read, must be divisible by the card block
* size.
* @return
* - SDMMC_OK on success
* - SDMMC_ERR_INVALID_SIZE if size is not divisible by 512 bytes
* - One of the error codes from SDMMC host controller
*/
sdmmc_err_t sdmmc_io_write_blocks(sdmmc_card_t* card, uint32_t function,
uint32_t addr, const void* src, size_t size);
/**
* Enable SDIO interrupt in the SDMMC host
*
* @param card pointer to card information structure previously initialized
* using sdmmc_card_init
* @return
* - SDMMC_OK on success
* - SDMMC_ERR_NOT_SUPPORTED if the host controller does not support
* IO interrupts
*/
sdmmc_err_t sdmmc_io_enable_int(sdmmc_card_t* card);
/**
* Block until an SDIO interrupt is received
*
* Slave uses D1 line to signal interrupt condition to the host.
* This function can be used to wait for the interrupt.
*
* @param card pointer to card information structure previously initialized
* using sdmmc_card_init
* @param timeout_ticks time to wait for the interrupt, in RTOS ticks
* @return
* - SDMMC_OK if the interrupt is received
* - SDMMC_ERR_NOT_SUPPORTED if the host controller does not support
* IO interrupts
* - SDMMC_ERR_TIMEOUT if the interrupt does not happen in timeout_ticks
*/
sdmmc_err_t sdmmc_io_wait_int(sdmmc_card_t* card, int timeout_ms);
/**
* Get the data of CIS region of a SDIO card.
*
* You may provide a buffer not sufficient to store all the CIS data. In this
* case, this functions store as much data into your buffer as possible. Also,
* this function will try to get and return the size required for you.
*
* @param card pointer to card information structure previously initialized
* using sdmmc_card_init
* @param out_buffer Output buffer of the CIS data
* @param buffer_size Size of the buffer.
* @param inout_cis_size Mandatory, pointer to a size, input and output.
* - input: Limitation of maximum searching range, should be 0 or larger than
* buffer_size. The function searches for CIS_CODE_END until this range. Set to
* 0 to search infinitely.
* - output: The size required to store all the CIS data, if CIS_CODE_END is found.
*
* @return
* - SDMMC_OK: on success
* - SDMMC_ERR_INVALID_RESPONSE: if the card does not (correctly) support CIS.
* - SDMMC_ERR_INVALID_SIZE: CIS_CODE_END found, but buffer_size is less than
* required size, which is stored in the inout_cis_size then.
* - SDMMC_ERR_NOT_FOUND: if the CIS_CODE_END not found. Increase input value of
* inout_cis_size or set it to 0, if you still want to search for the end;
* output value of inout_cis_size is invalid in this case.
* - and other error code return from sdmmc_io_read_bytes
*/
sdmmc_err_t sdmmc_io_get_cis_data(sdmmc_card_t* card, uint8_t* out_buffer, size_t buffer_size, size_t* inout_cis_size);
/**
* Parse and print the CIS information of a SDIO card.
*
* @note Not all the CIS codes and all kinds of tuples are supported. If you
* see some unresolved code, you can add the parsing of these code in
* sdmmc_io.c and contribute to the IDF through the Github repository.
*
* using sdmmc_card_init
* @param buffer Buffer to parse
* @param buffer_size Size of the buffer.
* @param fp File pointer to print to, set to NULL to print to stdout.
*
* @return
* - SDMMC_OK: on success
* - SDMMC_ERR_NOT_SUPPORTED: if the value from the card is not supported to be parsed.
* - SDMMC_ERR_INVALID_SIZE: if the CIS size fields are not correct.
*/
sdmmc_err_t sdmmc_io_print_cis_info(uint8_t* buffer, size_t buffer_size, FILE* fp);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,498 @@
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
* Adaptations to ESP-IDF Copyright (c) 2016 Espressif Systems (Shanghai) PTE LTD
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _SDMMC_DEFS_H_
#define _SDMMC_DEFS_H_
#include <stdint.h>
#include <limits.h>
/* MMC commands */ /* response type */
#define MMC_GO_IDLE_STATE 0 /* R0 */
#define MMC_SEND_OP_COND 1 /* R3 */
#define MMC_ALL_SEND_CID 2 /* R2 */
#define MMC_SET_RELATIVE_ADDR 3 /* R1 */
#define MMC_SWITCH 6 /* R1B */
#define MMC_SELECT_CARD 7 /* R1 */
#define MMC_SEND_EXT_CSD 8 /* R1 */
#define MMC_SEND_CSD 9 /* R2 */
#define MMC_SEND_CID 10 /* R1 */
#define MMC_READ_DAT_UNTIL_STOP 11 /* R1 */
#define MMC_STOP_TRANSMISSION 12 /* R1B */
#define MMC_SEND_STATUS 13 /* R1 */
#define MMC_SET_BLOCKLEN 16 /* R1 */
#define MMC_READ_BLOCK_SINGLE 17 /* R1 */
#define MMC_READ_BLOCK_MULTIPLE 18 /* R1 */
#define MMC_WRITE_DAT_UNTIL_STOP 20 /* R1 */
#define MMC_SET_BLOCK_COUNT 23 /* R1 */
#define MMC_WRITE_BLOCK_SINGLE 24 /* R1 */
#define MMC_WRITE_BLOCK_MULTIPLE 25 /* R1 */
#define MMC_APP_CMD 55 /* R1 */
/* SD commands */ /* response type */
#define SD_SEND_RELATIVE_ADDR 3 /* R6 */
#define SD_SEND_SWITCH_FUNC 6 /* R1 */
#define SD_SEND_IF_COND 8 /* R7 */
#define SD_READ_OCR 58 /* R3 */
#define SD_CRC_ON_OFF 59 /* R1 */
/* SD application commands */ /* response type */
#define SD_APP_SET_BUS_WIDTH 6 /* R1 */
#define SD_APP_SD_STATUS 13 /* R2 */
#define SD_APP_OP_COND 41 /* R3 */
#define SD_APP_SEND_SCR 51 /* R1 */
/* SD IO commands */
#define SD_IO_SEND_OP_COND 5 /* R4 */
#define SD_IO_RW_DIRECT 52 /* R5 */
#define SD_IO_RW_EXTENDED 53 /* R5 */
/* OCR bits */
#define MMC_OCR_MEM_READY (1<<31) /* memory power-up status bit */
#define MMC_OCR_ACCESS_MODE_MASK 0x60000000 /* bits 30:29 */
#define MMC_OCR_SECTOR_MODE (1<<30)
#define MMC_OCR_BYTE_MODE (1<<29)
#define MMC_OCR_3_5V_3_6V (1<<23)
#define MMC_OCR_3_4V_3_5V (1<<22)
#define MMC_OCR_3_3V_3_4V (1<<21)
#define MMC_OCR_3_2V_3_3V (1<<20)
#define MMC_OCR_3_1V_3_2V (1<<19)
#define MMC_OCR_3_0V_3_1V (1<<18)
#define MMC_OCR_2_9V_3_0V (1<<17)
#define MMC_OCR_2_8V_2_9V (1<<16)
#define MMC_OCR_2_7V_2_8V (1<<15)
#define MMC_OCR_2_6V_2_7V (1<<14)
#define MMC_OCR_2_5V_2_6V (1<<13)
#define MMC_OCR_2_4V_2_5V (1<<12)
#define MMC_OCR_2_3V_2_4V (1<<11)
#define MMC_OCR_2_2V_2_3V (1<<10)
#define MMC_OCR_2_1V_2_2V (1<<9)
#define MMC_OCR_2_0V_2_1V (1<<8)
#define MMC_OCR_1_65V_1_95V (1<<7)
#define SD_OCR_SDHC_CAP (1<<30)
#define SD_OCR_VOL_MASK 0xFF8000 /* bits 23:15 */
/* SD mode R1 response type bits */
#define MMC_R1_READY_FOR_DATA (1<<8) /* ready for next transfer */
#define MMC_R1_APP_CMD (1<<5) /* app. commands supported */
#define MMC_R1_SWITCH_ERROR (1<<7) /* switch command did not succeed */
/* SPI mode R1 response type bits */
#define SD_SPI_R1_IDLE_STATE (1<<0)
#define SD_SPI_R1_ERASE_RST (1<<1)
#define SD_SPI_R1_ILLEGAL_CMD (1<<2)
#define SD_SPI_R1_CMD_CRC_ERR (1<<3)
#define SD_SPI_R1_ERASE_SEQ_ERR (1<<4)
#define SD_SPI_R1_ADDR_ERR (1<<5)
#define SD_SPI_R1_PARAM_ERR (1<<6)
#define SD_SPI_R1_NO_RESPONSE (1<<7)
#define SDIO_R1_FUNC_NUM_ERR (1<<4)
/* 48-bit response decoding (32 bits w/o CRC) */
#define MMC_R1(resp) ((resp)[0])
#define MMC_R3(resp) ((resp)[0])
#define MMC_R4(resp) ((resp)[0])
#define MMC_R5(resp) ((resp)[0])
#define SD_R6(resp) ((resp)[0])
#define MMC_R1_CURRENT_STATE(resp) (((resp)[0] >> 9) & 0xf)
/* SPI mode response decoding */
#define SD_SPI_R1(resp) ((resp)[0] & 0xff)
#define SD_SPI_R2(resp) ((resp)[0] & 0xffff)
#define SD_SPI_R3(resp) ((resp)[0])
#define SD_SPI_R7(resp) ((resp)[0])
/* SPI mode data response decoding */
#define SD_SPI_DATA_RSP_VALID(resp_byte) (((resp_byte)&0x11)==0x1)
#define SD_SPI_DATA_RSP(resp_byte) (((resp_byte)>>1)&0x7)
#define SD_SPI_DATA_ACCEPTED 0x2
#define SD_SPI_DATA_CRC_ERROR 0x5
#define SD_SPI_DATA_WR_ERROR 0x6
/* RCA argument and response */
#define MMC_ARG_RCA(rca) ((rca) << 16)
#define SD_R6_RCA(resp) (SD_R6((resp)) >> 16)
/* bus width argument */
#define SD_ARG_BUS_WIDTH_1 0
#define SD_ARG_BUS_WIDTH_4 2
/* EXT_CSD fields */
#define EXT_CSD_BUS_WIDTH 183 /* WO */
#define EXT_CSD_HS_TIMING 185 /* R/W */
#define EXT_CSD_REV 192 /* RO */
#define EXT_CSD_STRUCTURE 194 /* RO */
#define EXT_CSD_CARD_TYPE 196 /* RO */
#define EXT_CSD_SEC_COUNT 212 /* RO */
#define EXT_CSD_PWR_CL_26_360 203 /* RO */
#define EXT_CSD_PWR_CL_52_360 202 /* RO */
#define EXT_CSD_PWR_CL_26_195 201 /* RO */
#define EXT_CSD_PWR_CL_52_195 200 /* RO */
#define EXT_CSD_POWER_CLASS 187 /* R/W */
#define EXT_CSD_CMD_SET 191 /* R/W */
#define EXT_CSD_S_CMD_SET 504 /* RO */
/* EXT_CSD field definitions */
#define EXT_CSD_CMD_SET_NORMAL (1U << 0)
#define EXT_CSD_CMD_SET_SECURE (1U << 1)
#define EXT_CSD_CMD_SET_CPSECURE (1U << 2)
/* EXT_CSD_HS_TIMING */
#define EXT_CSD_HS_TIMING_BC 0
#define EXT_CSD_HS_TIMING_HS 1
#define EXT_CSD_HS_TIMING_HS200 2
#define EXT_CSD_HS_TIMING_HS400 3
/* EXT_CSD_BUS_WIDTH */
#define EXT_CSD_BUS_WIDTH_1 0
#define EXT_CSD_BUS_WIDTH_4 1
#define EXT_CSD_BUS_WIDTH_8 2
#define EXT_CSD_BUS_WIDTH_4_DDR 5
#define EXT_CSD_BUS_WIDTH_8_DDR 6
/* EXT_CSD_CARD_TYPE */
/* The only currently valid values for this field are 0x01, 0x03, 0x07,
* 0x0B and 0x0F. */
#define EXT_CSD_CARD_TYPE_F_26M (1 << 0) /* SDR at "rated voltages */
#define EXT_CSD_CARD_TYPE_F_52M (1 << 1) /* SDR at "rated voltages */
#define EXT_CSD_CARD_TYPE_F_52M_1_8V (1 << 2) /* DDR, 1.8V or 3.3V I/O */
#define EXT_CSD_CARD_TYPE_F_52M_1_2V (1 << 3) /* DDR, 1.2V I/O */
#define EXT_CSD_CARD_TYPE_26M 0x01
#define EXT_CSD_CARD_TYPE_52M 0x03
#define EXT_CSD_CARD_TYPE_52M_V18 0x07
#define EXT_CSD_CARD_TYPE_52M_V12 0x0b
#define EXT_CSD_CARD_TYPE_52M_V12_18 0x0f
/* EXT_CSD MMC */
#define EXT_CSD_MMC_SIZE 512
/* MMC_SWITCH access mode */
#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */
#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits in value */
#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits in value */
#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */
/* MMC R2 response (CSD) */
#define MMC_CSD_CSDVER(resp) MMC_RSP_BITS((resp), 126, 2)
#define MMC_CSD_CSDVER_1_0 1
#define MMC_CSD_CSDVER_2_0 2
#define MMC_CSD_CSDVER_EXT_CSD 3
#define MMC_CSD_MMCVER(resp) MMC_RSP_BITS((resp), 122, 4)
#define MMC_CSD_MMCVER_1_0 0 /* MMC 1.0 - 1.2 */
#define MMC_CSD_MMCVER_1_4 1 /* MMC 1.4 */
#define MMC_CSD_MMCVER_2_0 2 /* MMC 2.0 - 2.2 */
#define MMC_CSD_MMCVER_3_1 3 /* MMC 3.1 - 3.3 */
#define MMC_CSD_MMCVER_4_0 4 /* MMC 4 */
#define MMC_CSD_READ_BL_LEN(resp) MMC_RSP_BITS((resp), 80, 4)
#define MMC_CSD_C_SIZE(resp) MMC_RSP_BITS((resp), 62, 12)
#define MMC_CSD_CAPACITY(resp) ((MMC_CSD_C_SIZE((resp))+1) << \
(MMC_CSD_C_SIZE_MULT((resp))+2))
#define MMC_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3)
/* MMC v1 R2 response (CID) */
#define MMC_CID_MID_V1(resp) MMC_RSP_BITS((resp), 104, 24)
#define MMC_CID_PNM_V1_CPY(resp, pnm) \
do { \
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
(pnm)[5] = MMC_RSP_BITS((resp), 56, 8); \
(pnm)[6] = MMC_RSP_BITS((resp), 48, 8); \
(pnm)[7] = '\0'; \
} while (0)
#define MMC_CID_REV_V1(resp) MMC_RSP_BITS((resp), 40, 8)
#define MMC_CID_PSN_V1(resp) MMC_RSP_BITS((resp), 16, 24)
#define MMC_CID_MDT_V1(resp) MMC_RSP_BITS((resp), 8, 8)
/* MMC v2 R2 response (CID) */
#define MMC_CID_MID_V2(resp) MMC_RSP_BITS((resp), 120, 8)
#define MMC_CID_OID_V2(resp) MMC_RSP_BITS((resp), 104, 16)
#define MMC_CID_PNM_V2_CPY(resp, pnm) \
do { \
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
(pnm)[5] = MMC_RSP_BITS((resp), 56, 8); \
(pnm)[6] = '\0'; \
} while (0)
#define MMC_CID_PSN_V2(resp) MMC_RSP_BITS((resp), 16, 32)
/* SD R2 response (CSD) */
#define SD_CSD_CSDVER(resp) MMC_RSP_BITS((resp), 126, 2)
#define SD_CSD_CSDVER_1_0 0
#define SD_CSD_CSDVER_2_0 1
#define SD_CSD_TAAC(resp) MMC_RSP_BITS((resp), 112, 8)
#define SD_CSD_TAAC_1_5_MSEC 0x26
#define SD_CSD_NSAC(resp) MMC_RSP_BITS((resp), 104, 8)
#define SD_CSD_SPEED(resp) MMC_RSP_BITS((resp), 96, 8)
#define SD_CSD_SPEED_25_MHZ 0x32
#define SD_CSD_SPEED_50_MHZ 0x5a
#define SD_CSD_CCC(resp) MMC_RSP_BITS((resp), 84, 12)
#define SD_CSD_CCC_BASIC (1 << 0) /* basic */
#define SD_CSD_CCC_BR (1 << 2) /* block read */
#define SD_CSD_CCC_BW (1 << 4) /* block write */
#define SD_CSD_CCC_ERASE (1 << 5) /* erase */
#define SD_CSD_CCC_WP (1 << 6) /* write protection */
#define SD_CSD_CCC_LC (1 << 7) /* lock card */
#define SD_CSD_CCC_AS (1 << 8) /*application specific*/
#define SD_CSD_CCC_IOM (1 << 9) /* I/O mode */
#define SD_CSD_CCC_SWITCH (1 << 10) /* switch */
#define SD_CSD_READ_BL_LEN(resp) MMC_RSP_BITS((resp), 80, 4)
#define SD_CSD_READ_BL_PARTIAL(resp) MMC_RSP_BITS((resp), 79, 1)
#define SD_CSD_WRITE_BLK_MISALIGN(resp) MMC_RSP_BITS((resp), 78, 1)
#define SD_CSD_READ_BLK_MISALIGN(resp) MMC_RSP_BITS((resp), 77, 1)
#define SD_CSD_DSR_IMP(resp) MMC_RSP_BITS((resp), 76, 1)
#define SD_CSD_C_SIZE(resp) MMC_RSP_BITS((resp), 62, 12)
#define SD_CSD_CAPACITY(resp) ((SD_CSD_C_SIZE((resp))+1) << \
(SD_CSD_C_SIZE_MULT((resp))+2))
#define SD_CSD_V2_C_SIZE(resp) MMC_RSP_BITS((resp), 48, 22)
#define SD_CSD_V2_CAPACITY(resp) ((SD_CSD_V2_C_SIZE((resp))+1) << 10)
#define SD_CSD_V2_BL_LEN 0x9 /* 512 */
#define SD_CSD_VDD_R_CURR_MIN(resp) MMC_RSP_BITS((resp), 59, 3)
#define SD_CSD_VDD_R_CURR_MAX(resp) MMC_RSP_BITS((resp), 56, 3)
#define SD_CSD_VDD_W_CURR_MIN(resp) MMC_RSP_BITS((resp), 53, 3)
#define SD_CSD_VDD_W_CURR_MAX(resp) MMC_RSP_BITS((resp), 50, 3)
#define SD_CSD_VDD_RW_CURR_100mA 0x7
#define SD_CSD_VDD_RW_CURR_80mA 0x6
#define SD_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3)
#define SD_CSD_ERASE_BLK_EN(resp) MMC_RSP_BITS((resp), 46, 1)
#define SD_CSD_SECTOR_SIZE(resp) MMC_RSP_BITS((resp), 39, 7) /* +1 */
#define SD_CSD_WP_GRP_SIZE(resp) MMC_RSP_BITS((resp), 32, 7) /* +1 */
#define SD_CSD_WP_GRP_ENABLE(resp) MMC_RSP_BITS((resp), 31, 1)
#define SD_CSD_R2W_FACTOR(resp) MMC_RSP_BITS((resp), 26, 3)
#define SD_CSD_WRITE_BL_LEN(resp) MMC_RSP_BITS((resp), 22, 4)
#define SD_CSD_RW_BL_LEN_2G 0xa
#define SD_CSD_RW_BL_LEN_1G 0x9
#define SD_CSD_WRITE_BL_PARTIAL(resp) MMC_RSP_BITS((resp), 21, 1)
#define SD_CSD_FILE_FORMAT_GRP(resp) MMC_RSP_BITS((resp), 15, 1)
#define SD_CSD_COPY(resp) MMC_RSP_BITS((resp), 14, 1)
#define SD_CSD_PERM_WRITE_PROTECT(resp) MMC_RSP_BITS((resp), 13, 1)
#define SD_CSD_TMP_WRITE_PROTECT(resp) MMC_RSP_BITS((resp), 12, 1)
#define SD_CSD_FILE_FORMAT(resp) MMC_RSP_BITS((resp), 10, 2)
/* SD R2 response (CID) */
#define SD_CID_MID(resp) MMC_RSP_BITS((resp), 120, 8)
#define SD_CID_OID(resp) MMC_RSP_BITS((resp), 104, 16)
#define SD_CID_PNM_CPY(resp, pnm) \
do { \
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
(pnm)[5] = '\0'; \
} while (0)
#define SD_CID_REV(resp) MMC_RSP_BITS((resp), 56, 8)
#define SD_CID_PSN(resp) MMC_RSP_BITS((resp), 24, 32)
#define SD_CID_MDT(resp) MMC_RSP_BITS((resp), 8, 12)
/* SCR (SD Configuration Register) */
#define SCR_STRUCTURE(scr) MMC_RSP_BITS((scr), 60, 4)
#define SCR_STRUCTURE_VER_1_0 0 /* Version 1.0 */
#define SCR_SD_SPEC(scr) MMC_RSP_BITS((scr), 56, 4)
#define SCR_SD_SPEC_VER_1_0 0 /* Version 1.0 and 1.01 */
#define SCR_SD_SPEC_VER_1_10 1 /* Version 1.10 */
#define SCR_SD_SPEC_VER_2 2 /* Version 2.00 or Version 3.0X */
#define SCR_DATA_STAT_AFTER_ERASE(scr) MMC_RSP_BITS((scr), 55, 1)
#define SCR_SD_SECURITY(scr) MMC_RSP_BITS((scr), 52, 3)
#define SCR_SD_SECURITY_NONE 0 /* no security */
#define SCR_SD_SECURITY_1_0 1 /* security protocol 1.0 */
#define SCR_SD_SECURITY_1_0_2 2 /* security protocol 1.0 */
#define SCR_SD_BUS_WIDTHS(scr) MMC_RSP_BITS((scr), 48, 4)
#define SCR_SD_BUS_WIDTHS_1BIT (1 << 0) /* 1bit (DAT0) */
#define SCR_SD_BUS_WIDTHS_4BIT (1 << 2) /* 4bit (DAT0-3) */
#define SCR_SD_SPEC3(scr) MMC_RSP_BITS((scr), 47, 1)
#define SCR_EX_SECURITY(scr) MMC_RSP_BITS((scr), 43, 4)
#define SCR_SD_SPEC4(scr) MMC_RSP_BITS((scr), 42, 1)
#define SCR_RESERVED(scr) MMC_RSP_BITS((scr), 34, 8)
#define SCR_CMD_SUPPORT_CMD23(scr) MMC_RSP_BITS((scr), 33, 1)
#define SCR_CMD_SUPPORT_CMD20(scr) MMC_RSP_BITS((scr), 32, 1)
#define SCR_RESERVED2(scr) MMC_RSP_BITS((scr), 0, 32)
/* Max supply current in SWITCH_FUNC response (in mA) */
#define SD_SFUNC_I_MAX(status) (MMC_RSP_BITS((uint32_t *)(status), 496, 16))
/* Supported flags in SWITCH_FUNC response */
#define SD_SFUNC_SUPPORTED(status, group) \
(MMC_RSP_BITS((uint32_t *)(status), 400 + (group - 1) * 16, 16))
/* Selected function in SWITCH_FUNC response */
#define SD_SFUNC_SELECTED(status, group) \
(MMC_RSP_BITS((uint32_t *)(status), 376 + (group - 1) * 4, 4))
/* Busy flags in SWITCH_FUNC response */
#define SD_SFUNC_BUSY(status, group) \
(MMC_RSP_BITS((uint32_t *)(status), 272 + (group - 1) * 16, 16))
/* Version of SWITCH_FUNC response */
#define SD_SFUNC_VER(status) (MMC_RSP_BITS((uint32_t *)(status), 368, 8))
#define SD_SFUNC_GROUP_MAX 6
#define SD_SFUNC_FUNC_MAX 15
#define SD_ACCESS_MODE 1 /* Function group 1, Access Mode */
#define SD_ACCESS_MODE_SDR12 0 /* 25 MHz clock */
#define SD_ACCESS_MODE_SDR25 1 /* 50 MHz clock */
#define SD_ACCESS_MODE_SDR50 2 /* UHS-I, 100 MHz clock */
#define SD_ACCESS_MODE_SDR104 3 /* UHS-I, 208 MHz clock */
#define SD_ACCESS_MODE_DDR50 4 /* UHS-I, 50 MHz clock, DDR */
/**
* @brief Extract up to 32 sequential bits from an array of 32-bit words
*
* Bits within the word are numbered in the increasing order from LSB to MSB.
*
* As an example, consider 2 32-bit words:
*
* 0x01234567 0x89abcdef
*
* On a little-endian system, the bytes are stored in memory as follows:
*
* 67 45 23 01 ef cd ab 89
*
* MMC_RSP_BITS will extact bits as follows:
*
* start=0 len=4 -> result=0x00000007
* start=0 len=12 -> result=0x00000567
* start=28 len=8 -> result=0x000000f0
* start=59 len=5 -> result=0x00000011
*
* @param src array of words to extract bits from
* @param start index of the first bit to extract
* @param len number of bits to extract, 1 to 32
* @return 32-bit word where requested bits start from LSB
*/
static inline uint32_t MMC_RSP_BITS(uint32_t *src, int start, int len)
{
uint32_t mask = (len % 32 == 0) ? UINT_MAX : UINT_MAX >> (32 - (len % 32));
size_t word = start / 32;
size_t shift = start % 32;
uint32_t right = src[word] >> shift;
uint32_t left = (len + shift <= 32) ? 0 : src[word + 1] << ((32 - shift) % 32);
return (left | right) & mask;
}
/* SD R4 response (IO OCR) */
#define SD_IO_OCR_MEM_READY (1<<31)
#define SD_IO_OCR_NUM_FUNCTIONS(ocr) (((ocr) >> 28) & 0x7)
#define SD_IO_OCR_MEM_PRESENT (1<<27)
#define SD_IO_OCR_MASK 0x00fffff0
/* CMD52 arguments */
#define SD_ARG_CMD52_READ (0<<31)
#define SD_ARG_CMD52_WRITE (1<<31)
#define SD_ARG_CMD52_FUNC_SHIFT 28
#define SD_ARG_CMD52_FUNC_MASK 0x7
#define SD_ARG_CMD52_EXCHANGE (1<<27)
#define SD_ARG_CMD52_REG_SHIFT 9
#define SD_ARG_CMD52_REG_MASK 0x1ffff
#define SD_ARG_CMD52_DATA_SHIFT 0
#define SD_ARG_CMD52_DATA_MASK 0xff
#define SD_R5_DATA(resp) ((resp)[0] & 0xff)
/* CMD53 arguments */
#define SD_ARG_CMD53_READ (0<<31)
#define SD_ARG_CMD53_WRITE (1<<31)
#define SD_ARG_CMD53_FUNC_SHIFT 28
#define SD_ARG_CMD53_FUNC_MASK 0x7
#define SD_ARG_CMD53_BLOCK_MODE (1<<27)
#define SD_ARG_CMD53_INCREMENT (1<<26)
#define SD_ARG_CMD53_REG_SHIFT 9
#define SD_ARG_CMD53_REG_MASK 0x1ffff
#define SD_ARG_CMD53_LENGTH_SHIFT 0
#define SD_ARG_CMD53_LENGTH_MASK 0x1ff
#define SD_ARG_CMD53_LENGTH_MAX 512
/* Card Common Control Registers (CCCR) */
#define SD_IO_CCCR_START 0x00000
#define SD_IO_CCCR_SIZE 0x100
#define SD_IO_CCCR_FN_ENABLE 0x02
#define SD_IO_CCCR_FN_READY 0x03
#define SD_IO_CCCR_INT_ENABLE 0x04
#define SD_IO_CCCR_INT_PENDING 0x05
#define SD_IO_CCCR_CTL 0x06
#define CCCR_CTL_RES (1<<3)
#define SD_IO_CCCR_BUS_WIDTH 0x07
#define CCCR_BUS_WIDTH_1 (0<<0)
#define CCCR_BUS_WIDTH_4 (2<<0)
#define CCCR_BUS_WIDTH_8 (3<<0)
#define CCCR_BUS_WIDTH_ECSI (1<<5)
#define SD_IO_CCCR_CARD_CAP 0x08
#define CCCR_CARD_CAP_LSC BIT(6)
#define CCCR_CARD_CAP_4BLS BIT(7)
#define SD_IO_CCCR_CISPTR 0x09
#define SD_IO_CCCR_BLKSIZEL 0x10
#define SD_IO_CCCR_BLKSIZEH 0x11
#define SD_IO_CCCR_HIGHSPEED 0x13
#define CCCR_HIGHSPEED_SUPPORT BIT(0)
#define CCCR_HIGHSPEED_ENABLE BIT(1)
/* Function Basic Registers (FBR) */
#define SD_IO_FBR_START 0x00100
#define SD_IO_FBR_SIZE 0x00700
/* Card Information Structure (CIS) */
#define SD_IO_CIS_START 0x01000
#define SD_IO_CIS_SIZE 0x17000
/* CIS tuple codes (based on PC Card 16) */
#define CISTPL_CODE_NULL 0x00
#define CISTPL_CODE_DEVICE 0x01
#define CISTPL_CODE_CHKSUM 0x10
#define CISTPL_CODE_VERS1 0x15
#define CISTPL_CODE_ALTSTR 0x16
#define CISTPL_CODE_CONFIG 0x1A
#define CISTPL_CODE_CFTABLE_ENTRY 0x1B
#define CISTPL_CODE_MANFID 0x20
#define CISTPL_CODE_FUNCID 0x21
#define TPLFID_FUNCTION_SDIO 0x0c
#define CISTPL_CODE_FUNCE 0x22
#define CISTPL_CODE_VENDER_BEGIN 0x80
#define CISTPL_CODE_VENDER_END 0x8F
#define CISTPL_CODE_SDIO_STD 0x91
#define CISTPL_CODE_SDIO_EXT 0x92
#define CISTPL_CODE_END 0xFF
/* Timing */
#define SDMMC_TIMING_LEGACY 0
#define SDMMC_TIMING_HIGHSPEED 1
#define SDMMC_TIMING_MMC_DDR52 2
#include "py/runtime.h"
// Logging macros
// #define ESP_LOGD(tag, string, ...) mp_printf(&mp_plat_print, string "\n" __VA_OPT__(,) __VA_ARGS__)
// #define ESP_LOGV(tag, string, ...) mp_printf(&mp_plat_print, string "\n" __VA_OPT__(,) __VA_ARGS__)
// #define ESP_LOGW(tag, string, ...) mp_printf(&mp_plat_print, string "\n" __VA_OPT__(,) __VA_ARGS__)
// #define ESP_LOGE(tag, string, ...) mp_printf(&mp_plat_print, string "\n" __VA_OPT__(,) __VA_ARGS__)
#define ESP_LOGD(tag, string, ...)
#define ESP_LOGV(tag, string, ...)
#define ESP_LOGW(tag, string, ...)
#define ESP_LOGE(tag, string, ...)
#define TSD_MIN(_x, _y) ( ( (_x) < (_y) ) ? (_x) : (_y) )
#endif //_SDMMC_DEFS_H_

View File

@ -0,0 +1,199 @@
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
* Adaptations to ESP-IDF Copyright (c) 2016 Espressif Systems (Shanghai) PTE LTD
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _SDMMC_TYPES_H_
#define _SDMMC_TYPES_H_
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
/**
* Decoded values from SD card Card Specific Data register
*/
typedef struct {
int csd_ver; /*!< CSD structure format */
int mmc_ver; /*!< MMC version (for CID format) */
int capacity; /*!< total number of sectors */
int sector_size; /*!< sector size in bytes */
int read_block_len; /*!< block length for reads */
int card_command_class; /*!< Card Command Class for SD */
int tr_speed; /*!< Max transfer speed */
} sdmmc_csd_t;
/**
* Decoded values from SD card Card IDentification register
*/
typedef struct {
int mfg_id; /*!< manufacturer identification number */
int oem_id; /*!< OEM/product identification number */
char name[8]; /*!< product name (MMC v1 has the longest) */
int revision; /*!< product revision */
int serial; /*!< product serial number */
int date; /*!< manufacturing date */
} sdmmc_cid_t;
/**
* Decoded values from SD Configuration Register
*/
typedef struct {
int sd_spec; /*!< SD Physical layer specification version, reported by card */
int bus_width; /*!< bus widths supported by card: BIT(0) — 1-bit bus, BIT(2) — 4-bit bus */
} sdmmc_scr_t;
/**
* Decoded values of Extended Card Specific Data
*/
typedef struct {
uint8_t power_class; /*!< Power class used by the card */
} sdmmc_ext_csd_t;
/**
* SD/MMC command response buffer
*/
typedef uint32_t sdmmc_response_t[4];
/**
* SD SWITCH_FUNC response buffer
*/
typedef struct {
uint32_t data[512 / 8 / sizeof(uint32_t)]; /*!< response data */
} sdmmc_switch_func_rsp_t;
typedef enum {
SDMMC_OK = 0,
SDMMC_ERR_NOT_SUPPORTED = 1,
SDMMC_ERR_INVALID_RESPONSE = 2,
SDMMC_ERR_TIMEOUT = 3,
SDMMC_ERR_NO_MEM = 4,
SDMMC_ERR_INVALID_SIZE = 5,
SDMMC_ERR_NO_CARD = 6,
SDMMC_ERR_INVALID_ARG = 7,
SDMMC_ERR_BUSY = 8,
} sdmmc_err_t;
/**
* SD/MMC command information
*/
typedef struct {
uint32_t opcode; /*!< SD or MMC command index */
uint32_t arg; /*!< SD/MMC command argument */
sdmmc_response_t response; /*!< response buffer */
void* data; /*!< buffer to send or read into */
size_t datalen; /*!< length of data buffer */
size_t blklen; /*!< block length */
int flags; /*!< see below */
/** @cond */
#define SCF_ITSDONE 0x0001 /*!< command is complete */
#define SCF_CMD(flags) ((flags) & 0x00f0)
#define SCF_CMD_AC 0x0000
#define SCF_CMD_ADTC 0x0010
#define SCF_CMD_BC 0x0020
#define SCF_CMD_BCR 0x0030
#define SCF_CMD_READ 0x0040 /*!< read command (data expected) */
#define SCF_RSP_BSY 0x0100
#define SCF_RSP_136 0x0200
#define SCF_RSP_CRC 0x0400
#define SCF_RSP_IDX 0x0800
#define SCF_RSP_PRESENT 0x1000
/* response types */
#define SCF_RSP_R0 0 /*!< none */
#define SCF_RSP_R1 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
#define SCF_RSP_R1B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY)
#define SCF_RSP_R2 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_136)
#define SCF_RSP_R3 (SCF_RSP_PRESENT)
#define SCF_RSP_R4 (SCF_RSP_PRESENT)
#define SCF_RSP_R5 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
#define SCF_RSP_R5B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY)
#define SCF_RSP_R6 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
#define SCF_RSP_R7 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX)
/* special flags */
#define SCF_WAIT_BUSY 0x2000 /*!< Wait for completion of card busy signal before returning */
#define SCF_AUTO_STOP 0x4000 /*!< Auto stop with command 12 */
/** @endcond */
sdmmc_err_t error; /*!< error returned from transfer */
int timeout_ms; /*!< response timeout, in milliseconds */
} sdmmc_command_t;
/**
* SD/MMC Host description
*
* This structure defines properties of SD/MMC host and functions
* of SD/MMC host which can be used by upper layers.
*/
#define BIT(x) (1 << x)
typedef struct {
uint32_t flags; /*!< flags defining host properties */
#define SDMMC_HOST_FLAG_1BIT BIT(0) /*!< host supports 1-line SD and MMC protocol */
#define SDMMC_HOST_FLAG_4BIT BIT(1) /*!< host supports 4-line SD and MMC protocol */
#define SDMMC_HOST_FLAG_8BIT BIT(2) /*!< host supports 8-line MMC protocol */
#define SDMMC_HOST_FLAG_SPI BIT(3) /*!< host supports SPI protocol */
#define SDMMC_HOST_FLAG_DDR BIT(4) /*!< host supports DDR mode for SD/MMC */
#define SDMMC_HOST_FLAG_DEINIT_ARG BIT(5) /*!< host `deinit` function called with the slot argument */
int slot; /*!< slot number, to be passed to host functions */
int max_freq_khz; /*!< max frequency supported by the host */
#define SDMMC_FREQ_DEFAULT 20000 /*!< SD/MMC Default speed (limited by clock divider) */
#define SDMMC_FREQ_HIGHSPEED 40000 /*!< SD High speed (limited by clock divider) */
#define SDMMC_FREQ_PROBING 400 /*!< SD/MMC probing speed */
#define SDMMC_FREQ_52M 52000 /*!< MMC 52MHz speed */
#define SDMMC_FREQ_26M 26000 /*!< MMC 26MHz speed */
float io_voltage; /*!< I/O voltage used by the controller (voltage switching is not supported) */
sdmmc_err_t (*init)(void); /*!< Host function to initialize the driver */
sdmmc_err_t (*set_bus_width)(int slot, size_t width); /*!< host function to set bus width */
size_t (*get_bus_width)(int slot); /*!< host function to get bus width */
sdmmc_err_t (*set_bus_ddr_mode)(int slot, bool ddr_enable); /*!< host function to set DDR mode */
sdmmc_err_t (*set_card_clk)(int slot, uint32_t freq_khz); /*!< host function to set card clock frequency */
sdmmc_err_t (*do_transaction)(int slot, sdmmc_command_t* cmdinfo); /*!< host function to do a transaction */
union {
sdmmc_err_t (*deinit)(void); /*!< host function to deinitialize the driver */
sdmmc_err_t (*deinit_p)(int slot); /*!< host function to deinitialize the driver, called with the `slot` */
};
sdmmc_err_t (*io_int_enable)(int slot); /*!< Host function to enable SDIO interrupt line */
sdmmc_err_t (*io_int_wait)(int slot, int timeout_ms); /*!< Host function to wait for SDIO interrupt line to be active */
int command_timeout_ms; /*!< timeout, in milliseconds, of a single command. Set to 0 to use the default value. */
} sdmmc_host_t;
/**
* SD/MMC card information structure
*/
typedef struct {
sdmmc_host_t host; /*!< Host with which the card is associated */
uint32_t ocr; /*!< OCR (Operation Conditions Register) value */
union {
sdmmc_cid_t cid; /*!< decoded CID (Card IDentification) register value */
sdmmc_response_t raw_cid; /*!< raw CID of MMC card to be decoded
after the CSD is fetched in the data transfer mode*/
};
sdmmc_csd_t csd; /*!< decoded CSD (Card-Specific Data) register value */
sdmmc_scr_t scr; /*!< decoded SCR (SD card Configuration Register) value */
sdmmc_ext_csd_t ext_csd; /*!< decoded EXT_CSD (Extended Card Specific Data) register value */
uint16_t rca; /*!< RCA (Relative Card Address) */
uint16_t max_freq_khz; /*!< Maximum frequency, in kHz, supported by the card */
uint32_t is_mem : 1; /*!< Bit indicates if the card is a memory card */
uint32_t is_sdio : 1; /*!< Bit indicates if the card is an IO card */
uint32_t is_mmc : 1; /*!< Bit indicates if the card is MMC */
uint32_t num_io_functions : 3; /*!< If is_sdio is 1, contains the number of IO functions on the card */
uint32_t log_bus_width : 2; /*!< log2(bus width supported by card) */
uint32_t is_ddr : 1; /*!< Card supports DDR mode */
uint32_t reserved : 23; /*!< Reserved for future expansion */
} sdmmc_card_t;
// OS abstraction layer (copied from TinyUSB)
void osal_task_delay(uint32_t msec);
#endif // _SDMMC_TYPES_H_

501
lib/sdmmc/sdmmc_cmd.c Normal file
View File

@ -0,0 +1,501 @@
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
* Adaptations to ESP-IDF Copyright (c) 2016-2018 Espressif Systems (Shanghai) PTE LTD
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
#include "sdmmc_common.h"
sdmmc_err_t sdmmc_send_cmd(sdmmc_card_t* card, sdmmc_command_t* cmd)
{
if (card->host.command_timeout_ms != 0) {
cmd->timeout_ms = card->host.command_timeout_ms;
} else if (cmd->timeout_ms == 0) {
cmd->timeout_ms = SDMMC_DEFAULT_CMD_TIMEOUT_MS;
}
int slot = card->host.slot;
ESP_LOGV(TAG, "sending cmd slot=%d op=%d arg=%x flags=%x data=%p blklen=%d datalen=%d timeout=%d",
slot, cmd->opcode, cmd->arg, cmd->flags, cmd->data, cmd->blklen, cmd->datalen, cmd->timeout_ms);
sdmmc_err_t err = (*card->host.do_transaction)(slot, cmd);
if (err != 0) {
ESP_LOGD(TAG, "cmd=%d, sdmmc_req_run returned 0x%x", cmd->opcode, err);
return err;
}
ESP_LOGV(TAG, "cmd response %08x %08x %08x %08x err=0x%x state=%d",
cmd->response[0],
cmd->response[1],
cmd->response[2],
cmd->response[3],
cmd->error,
MMC_R1_CURRENT_STATE(cmd->response));
return cmd->error;
}
sdmmc_err_t sdmmc_send_app_cmd(sdmmc_card_t* card, sdmmc_command_t* cmd)
{
sdmmc_command_t app_cmd = {
.opcode = MMC_APP_CMD,
.flags = SCF_CMD_AC | SCF_RSP_R1,
.arg = MMC_ARG_RCA(card->rca),
};
sdmmc_err_t err = sdmmc_send_cmd(card, &app_cmd);
if (err != SDMMC_OK) {
return err;
}
// Check APP_CMD status bit (only in SD mode)
if (!host_is_spi(card) && !(MMC_R1(app_cmd.response) & MMC_R1_APP_CMD)) {
ESP_LOGW(TAG, "card doesn't support APP_CMD");
return SDMMC_ERR_NOT_SUPPORTED;
}
return sdmmc_send_cmd(card, cmd);
}
sdmmc_err_t sdmmc_send_cmd_go_idle_state(sdmmc_card_t* card)
{
sdmmc_command_t cmd = {
.opcode = MMC_GO_IDLE_STATE,
.flags = SCF_CMD_BC | SCF_RSP_R0,
};
sdmmc_err_t err = sdmmc_send_cmd(card, &cmd);
if (host_is_spi(card)) {
/* To enter SPI mode, CMD0 needs to be sent twice (see figure 4-1 in
* SD Simplified spec v4.10). Some cards enter SD mode on first CMD0,
* so don't expect the above command to succeed.
* SCF_RSP_R1 flag below tells the lower layer to expect correct R1
* response (in SPI mode).
*/
(void) err;
osal_task_delay(SDMMC_GO_IDLE_DELAY_MS);
cmd.flags |= SCF_RSP_R1;
err = sdmmc_send_cmd(card, &cmd);
}
if (err == SDMMC_OK) {
osal_task_delay(SDMMC_GO_IDLE_DELAY_MS);
}
return err;
}
sdmmc_err_t sdmmc_send_cmd_send_if_cond(sdmmc_card_t* card, uint32_t ocr)
{
const uint8_t pattern = 0xaa; /* any pattern will do here */
sdmmc_command_t cmd = {
.opcode = SD_SEND_IF_COND,
.arg = (((ocr & SD_OCR_VOL_MASK) != 0) << 8) | pattern,
.flags = SCF_CMD_BCR | SCF_RSP_R7,
};
sdmmc_err_t err = sdmmc_send_cmd(card, &cmd);
if (err != SDMMC_OK) {
return err;
}
uint8_t response = cmd.response[0] & 0xff;
if (response != pattern) {
ESP_LOGD(TAG, "%s: received=0x%x expected=0x%x", __func__, response, pattern);
return SDMMC_ERR_INVALID_RESPONSE;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_send_cmd_send_op_cond(sdmmc_card_t* card, uint32_t ocr, uint32_t *ocrp)
{
sdmmc_err_t err;
sdmmc_command_t cmd = {
.arg = ocr,
.flags = SCF_CMD_BCR | SCF_RSP_R3,
.opcode = SD_APP_OP_COND
};
int nretries = SDMMC_SEND_OP_COND_MAX_RETRIES;
int err_cnt = SDMMC_SEND_OP_COND_MAX_ERRORS;
for (; nretries != 0; --nretries) {
bzero(&cmd, sizeof cmd);
cmd.arg = ocr;
cmd.flags = SCF_CMD_BCR | SCF_RSP_R3;
if (!card->is_mmc) { /* SD mode */
cmd.opcode = SD_APP_OP_COND;
err = sdmmc_send_app_cmd(card, &cmd);
} else { /* MMC mode */
cmd.arg &= ~MMC_OCR_ACCESS_MODE_MASK;
cmd.arg |= MMC_OCR_SECTOR_MODE;
cmd.opcode = MMC_SEND_OP_COND;
err = sdmmc_send_cmd(card, &cmd);
}
if (err != SDMMC_OK) {
if (--err_cnt == 0) {
ESP_LOGD(TAG, "%s: sdmmc_send_app_cmd err=0x%x", __func__, err);
return err;
} else {
ESP_LOGV(TAG, "%s: ignoring err=0x%x", __func__, err);
continue;
}
}
// In SD protocol, card sets MEM_READY bit in OCR when it is ready.
// In SPI protocol, card clears IDLE_STATE bit in R1 response.
if (!host_is_spi(card)) {
if ((MMC_R3(cmd.response) & MMC_OCR_MEM_READY) ||
ocr == 0) {
break;
}
} else {
if ((SD_SPI_R1(cmd.response) & SD_SPI_R1_IDLE_STATE) == 0) {
break;
}
}
osal_task_delay(10);
}
if (nretries == 0) {
return SDMMC_ERR_TIMEOUT;
}
if (ocrp) {
*ocrp = MMC_R3(cmd.response);
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_send_cmd_read_ocr(sdmmc_card_t *card, uint32_t *ocrp)
{
assert(ocrp);
sdmmc_command_t cmd = {
.opcode = SD_READ_OCR,
.flags = SCF_CMD_BCR | SCF_RSP_R2
};
sdmmc_err_t err = sdmmc_send_cmd(card, &cmd);
if (err != SDMMC_OK) {
return err;
}
*ocrp = SD_SPI_R3(cmd.response);
return SDMMC_OK;
}
sdmmc_err_t sdmmc_send_cmd_all_send_cid(sdmmc_card_t* card, sdmmc_response_t* out_raw_cid)
{
assert(out_raw_cid);
sdmmc_command_t cmd = {
.opcode = MMC_ALL_SEND_CID,
.flags = SCF_CMD_BCR | SCF_RSP_R2
};
sdmmc_err_t err = sdmmc_send_cmd(card, &cmd);
if (err != SDMMC_OK) {
return err;
}
memcpy(out_raw_cid, &cmd.response, sizeof(sdmmc_response_t));
return SDMMC_OK;
}
sdmmc_err_t sdmmc_send_cmd_send_cid(sdmmc_card_t *card, sdmmc_cid_t *out_cid)
{
assert(out_cid);
assert(host_is_spi(card) && "SEND_CID should only be used in SPI mode");
assert(!card->is_mmc && "MMC cards are not supported in SPI mode");
sdmmc_response_t buf;
sdmmc_command_t cmd = {
.opcode = MMC_SEND_CID,
.flags = SCF_CMD_READ | SCF_CMD_ADTC,
.arg = 0,
.data = &buf[0],
.datalen = sizeof(buf)
};
sdmmc_err_t err = sdmmc_send_cmd(card, &cmd);
if (err != SDMMC_OK) {
return err;
}
sdmmc_flip_byte_order(buf, sizeof(buf));
return sdmmc_decode_cid(buf, out_cid);
}
sdmmc_err_t sdmmc_send_cmd_set_relative_addr(sdmmc_card_t* card, uint16_t* out_rca)
{
assert(out_rca);
sdmmc_command_t cmd = {
.opcode = SD_SEND_RELATIVE_ADDR,
.flags = SCF_CMD_BCR | SCF_RSP_R6
};
/* MMC cards expect us to set the RCA.
* Set RCA to 1 since we don't support multiple cards on the same bus, for now.
*/
uint16_t mmc_rca = 1;
if (card->is_mmc) {
cmd.arg = MMC_ARG_RCA(mmc_rca);
}
sdmmc_err_t err = sdmmc_send_cmd(card, &cmd);
if (err != SDMMC_OK) {
return err;
}
*out_rca = (card->is_mmc) ? mmc_rca : SD_R6_RCA(cmd.response);
return SDMMC_OK;
}
sdmmc_err_t sdmmc_send_cmd_set_blocklen(sdmmc_card_t* card, sdmmc_csd_t* csd)
{
sdmmc_command_t cmd = {
.opcode = MMC_SET_BLOCKLEN,
.arg = csd->sector_size,
.flags = SCF_CMD_AC | SCF_RSP_R1
};
return sdmmc_send_cmd(card, &cmd);
}
sdmmc_err_t sdmmc_send_cmd_send_csd(sdmmc_card_t* card, sdmmc_csd_t* out_csd)
{
/* The trick with SEND_CSD is that in SPI mode, it acts as a data read
* command, while in SD mode it is an AC command with R2 response.
*/
sdmmc_response_t spi_buf;
const bool is_spi = host_is_spi(card);
sdmmc_command_t cmd = {
.opcode = MMC_SEND_CSD,
.arg = is_spi ? 0 : MMC_ARG_RCA(card->rca),
.flags = is_spi ? (SCF_CMD_READ | SCF_CMD_ADTC | SCF_RSP_R1) :
(SCF_CMD_AC | SCF_RSP_R2),
.data = is_spi ? &spi_buf[0] : 0,
.datalen = is_spi ? sizeof(spi_buf) : 0,
};
sdmmc_err_t err = sdmmc_send_cmd(card, &cmd);
if (err != SDMMC_OK) {
return err;
}
uint32_t* ptr = cmd.response;
if (is_spi) {
sdmmc_flip_byte_order(spi_buf, sizeof(spi_buf));
ptr = spi_buf;
}
if (card->is_mmc) {
err = sdmmc_mmc_decode_csd(cmd.response, out_csd);
} else {
err = sdmmc_decode_csd(ptr, out_csd);
}
return err;
}
sdmmc_err_t sdmmc_send_cmd_select_card(sdmmc_card_t* card, uint32_t rca)
{
/* Don't expect to see a response when de-selecting a card */
uint32_t response = (rca == 0) ? 0 : SCF_RSP_R1;
sdmmc_command_t cmd = {
.opcode = MMC_SELECT_CARD,
.arg = MMC_ARG_RCA(rca),
.flags = SCF_CMD_AC | response
};
return sdmmc_send_cmd(card, &cmd);
}
sdmmc_err_t sdmmc_send_cmd_send_scr(sdmmc_card_t* card, sdmmc_scr_t *out_scr)
{
size_t datalen = 8;
uint32_t buf[datalen];
sdmmc_command_t cmd = {
.data = buf,
.datalen = datalen,
.blklen = datalen,
.flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1,
.opcode = SD_APP_SEND_SCR
};
sdmmc_err_t err = sdmmc_send_app_cmd(card, &cmd);
if (err == SDMMC_OK) {
err = sdmmc_decode_scr(buf, out_scr);
}
return err;
}
sdmmc_err_t sdmmc_send_cmd_set_bus_width(sdmmc_card_t* card, int width)
{
sdmmc_command_t cmd = {
.opcode = SD_APP_SET_BUS_WIDTH,
.flags = SCF_RSP_R1 | SCF_CMD_AC,
.arg = (width == 4) ? SD_ARG_BUS_WIDTH_4 : SD_ARG_BUS_WIDTH_1,
};
return sdmmc_send_app_cmd(card, &cmd);
}
sdmmc_err_t sdmmc_send_cmd_crc_on_off(sdmmc_card_t* card, bool crc_enable)
{
assert(host_is_spi(card) && "CRC_ON_OFF can only be used in SPI mode");
sdmmc_command_t cmd = {
.opcode = SD_CRC_ON_OFF,
.arg = crc_enable ? 1 : 0,
.flags = SCF_CMD_AC | SCF_RSP_R1
};
return sdmmc_send_cmd(card, &cmd);
}
sdmmc_err_t sdmmc_send_cmd_send_status(sdmmc_card_t* card, uint32_t* out_status)
{
sdmmc_command_t cmd = {
.opcode = MMC_SEND_STATUS,
.arg = MMC_ARG_RCA(card->rca),
.flags = SCF_CMD_AC | SCF_RSP_R1
};
sdmmc_err_t err = sdmmc_send_cmd(card, &cmd);
if (err != SDMMC_OK) {
return err;
}
if (out_status) {
*out_status = MMC_R1(cmd.response);
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src,
size_t start_block, size_t block_count)
{
sdmmc_err_t err = SDMMC_OK;
size_t block_size = card->csd.sector_size;
if ((intptr_t)src % 4 == 0) {
err = sdmmc_write_sectors_dma(card, src, start_block, block_count);
} else {
// SDMMC peripheral needs DMA-capable buffers. Split the write into
// separate single block writes, if needed, and allocate a temporary
// DMA-capable buffer.
uint32_t tmp_buf[block_size / sizeof(uint32_t)];
const uint8_t* cur_src = (const uint8_t*) src;
for (size_t i = 0; i < block_count; ++i) {
memcpy(tmp_buf, cur_src, block_size);
cur_src += block_size;
err = sdmmc_write_sectors_dma(card, tmp_buf, start_block + i, 1);
if (err != SDMMC_OK) {
ESP_LOGD(TAG, "%s: error 0x%x writing block %d+%d",
__func__, err, start_block, i);
break;
}
}
}
return err;
}
sdmmc_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src,
size_t start_block, size_t block_count)
{
if (start_block + block_count > (size_t) card->csd.capacity) {
return SDMMC_ERR_INVALID_SIZE;
}
size_t block_size = card->csd.sector_size;
sdmmc_command_t cmd = {
.flags = SCF_CMD_ADTC | SCF_RSP_R1,
.blklen = block_size,
.data = (void*) src,
.datalen = block_count * block_size,
.timeout_ms = SDMMC_WRITE_CMD_TIMEOUT_MS
};
if (block_count == 1) {
cmd.opcode = MMC_WRITE_BLOCK_SINGLE;
} else {
cmd.opcode = MMC_WRITE_BLOCK_MULTIPLE;
cmd.flags |= SCF_AUTO_STOP;
}
if (card->ocr & SD_OCR_SDHC_CAP) {
cmd.arg = start_block;
} else {
cmd.arg = start_block * block_size;
}
sdmmc_err_t err = sdmmc_send_cmd(card, &cmd);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x", __func__, err);
return err;
}
uint32_t status = 0;
size_t count = 0;
while (!host_is_spi(card) && !(status & MMC_R1_READY_FOR_DATA)) {
// TODO: add some timeout here
err = sdmmc_send_cmd_send_status(card, &status);
if (err != SDMMC_OK) {
return err;
}
if (++count % 10 == 0) {
ESP_LOGV(TAG, "waiting for card to become ready (%d)", count);
}
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_read_sectors(sdmmc_card_t* card, void* dst,
size_t start_block, size_t block_count)
{
sdmmc_err_t err = SDMMC_OK;
size_t block_size = card->csd.sector_size;
if ((intptr_t)dst % 4 == 0) {
err = sdmmc_read_sectors_dma(card, dst, start_block, block_count);
} else {
// SDMMC peripheral needs DMA-capable buffers. Split the read into
// separate single block reads, if needed, and allocate a temporary
// DMA-capable buffer.
uint32_t tmp_buf[block_size / sizeof(uint32_t)];
uint8_t* cur_dst = (uint8_t*) dst;
for (size_t i = 0; i < block_count; ++i) {
err = sdmmc_read_sectors_dma(card, tmp_buf, start_block + i, 1);
if (err != SDMMC_OK) {
ESP_LOGD(TAG, "%s: error 0x%x writing block %d+%d",
__func__, err, start_block, i);
break;
}
memcpy(cur_dst, tmp_buf, block_size);
cur_dst += block_size;
}
}
return err;
}
sdmmc_err_t sdmmc_read_sectors_dma(sdmmc_card_t* card, void* dst,
size_t start_block, size_t block_count)
{
if (start_block + block_count > (size_t) card->csd.capacity) {
return SDMMC_ERR_INVALID_SIZE;
}
size_t block_size = card->csd.sector_size;
sdmmc_command_t cmd = {
.flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1,
.blklen = block_size,
.data = (void*) dst,
.datalen = block_count * block_size
};
if (block_count == 1) {
cmd.opcode = MMC_READ_BLOCK_SINGLE;
} else {
cmd.opcode = MMC_READ_BLOCK_MULTIPLE;
cmd.flags |= SCF_AUTO_STOP;
}
if (card->ocr & SD_OCR_SDHC_CAP) {
cmd.arg = start_block;
} else {
cmd.arg = start_block * block_size;
}
sdmmc_err_t err = sdmmc_send_cmd(card, &cmd);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x", __func__, err);
return err;
}
uint32_t status = 0;
size_t count = 0;
while (!host_is_spi(card) && !(status & MMC_R1_READY_FOR_DATA)) {
// TODO: add some timeout here
err = sdmmc_send_cmd_send_status(card, &status);
if (err != SDMMC_OK) {
return err;
}
if (++count % 10 == 0) {
ESP_LOGV(TAG, "waiting for card to become ready (%d)", count);
}
}
return SDMMC_OK;
}

314
lib/sdmmc/sdmmc_common.c Normal file
View File

@ -0,0 +1,314 @@
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
* Adaptations to ESP-IDF Copyright (c) 2016-2018 Espressif Systems (Shanghai) PTE LTD
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
#include "sdmmc_common.h"
sdmmc_err_t sdmmc_init_ocr(sdmmc_card_t* card)
{
sdmmc_err_t err;
/* In SPI mode, READ_OCR (CMD58) command is used to figure out which voltage
* ranges the card can support. This step is skipped since 1.8V isn't
* supported on the ESP32.
*/
uint32_t host_ocr = get_host_ocr(card->host.io_voltage);
if ((card->ocr & SD_OCR_SDHC_CAP) != 0) {
host_ocr |= SD_OCR_SDHC_CAP;
}
/* Send SEND_OP_COND (ACMD41) command to the card until it becomes ready. */
err = sdmmc_send_cmd_send_op_cond(card, host_ocr, &card->ocr);
/* If time-out, re-try send_op_cond as MMC */
if (err == SDMMC_ERR_TIMEOUT && !host_is_spi(card)) {
ESP_LOGD(TAG, "send_op_cond timeout, trying MMC");
card->is_mmc = 1;
err = sdmmc_send_cmd_send_op_cond(card, host_ocr, &card->ocr);
}
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: send_op_cond (1) returned 0x%x", __func__, err);
return err;
}
if (host_is_spi(card)) {
err = sdmmc_send_cmd_read_ocr(card, &card->ocr);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: read_ocr returned 0x%x", __func__, err);
return err;
}
}
ESP_LOGD(TAG, "host_ocr=0x%x card_ocr=0x%x", host_ocr, card->ocr);
/* Clear all voltage bits in host's OCR which the card doesn't support.
* Don't touch CCS bit because in SPI mode cards don't report CCS in ACMD41
* response.
*/
host_ocr &= (card->ocr | (~SD_OCR_VOL_MASK));
ESP_LOGD(TAG, "sdmmc_card_init: host_ocr=%08x, card_ocr=%08x", host_ocr, card->ocr);
return SDMMC_OK;
}
sdmmc_err_t sdmmc_init_cid(sdmmc_card_t* card)
{
sdmmc_err_t err;
sdmmc_response_t raw_cid;
if (!host_is_spi(card)) {
err = sdmmc_send_cmd_all_send_cid(card, &raw_cid);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: all_send_cid returned 0x%x", __func__, err);
return err;
}
if (!card->is_mmc) {
err = sdmmc_decode_cid(raw_cid, &card->cid);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: decoding CID failed (0x%x)", __func__, err);
return err;
}
} else {
/* For MMC, need to know CSD to decode CID. But CSD can only be read
* in data transfer mode, and it is not possible to read CID in data
* transfer mode. We temporiliy store the raw cid and do the
* decoding after the RCA is set and the card is in data transfer
* mode.
*/
memcpy(card->raw_cid, raw_cid, sizeof(sdmmc_response_t));
}
} else {
err = sdmmc_send_cmd_send_cid(card, &card->cid);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: send_cid returned 0x%x", __func__, err);
return err;
}
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_init_rca(sdmmc_card_t* card)
{
sdmmc_err_t err;
err = sdmmc_send_cmd_set_relative_addr(card, &card->rca);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: set_relative_addr returned 0x%x", __func__, err);
return err;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_init_mmc_decode_cid(sdmmc_card_t* card)
{
sdmmc_err_t err;
sdmmc_response_t raw_cid;
memcpy(raw_cid, card->raw_cid, sizeof(raw_cid));
err = sdmmc_mmc_decode_cid(card->csd.mmc_ver, raw_cid, &card->cid);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: decoding CID failed (0x%x)", __func__, err);
return err;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_init_csd(sdmmc_card_t* card)
{
assert(card->is_mem == 1);
/* Get and decode the contents of CSD register. Determine card capacity. */
sdmmc_err_t err = sdmmc_send_cmd_send_csd(card, &card->csd);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: send_csd returned 0x%x", __func__, err);
return err;
}
const size_t max_sdsc_capacity = UINT32_MAX / card->csd.sector_size + 1;
if (!(card->ocr & SD_OCR_SDHC_CAP) &&
(size_t) card->csd.capacity > max_sdsc_capacity) {
ESP_LOGW(TAG, "%s: SDSC card reports capacity=%u. Limiting to %u.",
__func__, card->csd.capacity, max_sdsc_capacity);
card->csd.capacity = max_sdsc_capacity;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_init_select_card(sdmmc_card_t* card)
{
assert(!host_is_spi(card));
sdmmc_err_t err = sdmmc_send_cmd_select_card(card, card->rca);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: select_card returned 0x%x", __func__, err);
return err;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_init_card_hs_mode(sdmmc_card_t* card)
{
sdmmc_err_t err = SDMMC_ERR_NOT_SUPPORTED;
if (card->is_mem && !card->is_mmc) {
err = sdmmc_enable_hs_mode_and_check(card);
} else if (card->is_sdio) {
err = sdmmc_io_enable_hs_mode(card);
} else if (card->is_mmc){
err = sdmmc_mmc_enable_hs_mode(card);
}
if (err == SDMMC_ERR_NOT_SUPPORTED) {
ESP_LOGD(TAG, "%s: host supports HS mode, but card doesn't", __func__);
card->max_freq_khz = SDMMC_FREQ_DEFAULT;
} else if (err != SDMMC_OK) {
return err;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_init_host_bus_width(sdmmc_card_t* card)
{
int bus_width = 1;
if ((card->host.flags & SDMMC_HOST_FLAG_4BIT) &&
(card->log_bus_width == 2)) {
bus_width = 4;
} else if ((card->host.flags & SDMMC_HOST_FLAG_8BIT) &&
(card->log_bus_width == 3)) {
bus_width = 8;
}
ESP_LOGD(TAG, "%s: using %d-bit bus", __func__, bus_width);
if (bus_width > 1) {
sdmmc_err_t err = (*card->host.set_bus_width)(card->host.slot, bus_width);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "host.set_bus_width failed (0x%x)", err);
return err;
}
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_init_host_frequency(sdmmc_card_t* card)
{
assert(card->max_freq_khz <= card->host.max_freq_khz);
/* Find highest frequency in the following list,
* which is below card->max_freq_khz.
*/
const uint32_t freq_values[] = {
SDMMC_FREQ_52M,
SDMMC_FREQ_HIGHSPEED,
SDMMC_FREQ_26M,
SDMMC_FREQ_DEFAULT
//NOTE: in sdspi mode, 20MHz may not work. in that case, add 10MHz here.
};
const int n_freq_values = sizeof(freq_values) / sizeof(freq_values[0]);
uint32_t selected_freq = SDMMC_FREQ_PROBING;
for (int i = 0; i < n_freq_values; ++i) {
uint32_t freq = freq_values[i];
if (card->max_freq_khz >= freq) {
selected_freq = freq;
break;
}
}
ESP_LOGD(TAG, "%s: using %d kHz bus frequency", __func__, selected_freq);
if (selected_freq > SDMMC_FREQ_PROBING) {
sdmmc_err_t err = (*card->host.set_card_clk)(card->host.slot, selected_freq);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "failed to switch bus frequency (0x%x)", err);
return err;
}
}
if (card->is_ddr) {
if (card->host.set_bus_ddr_mode == NULL) {
ESP_LOGE(TAG, "host doesn't support DDR mode or voltage switching");
return SDMMC_ERR_NOT_SUPPORTED;
}
sdmmc_err_t err = (*card->host.set_bus_ddr_mode)(card->host.slot, true);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "failed to switch bus to DDR mode (0x%x)", err);
return err;
}
}
return SDMMC_OK;
}
void sdmmc_flip_byte_order(uint32_t* response, size_t size)
{
assert(size % (2 * sizeof(uint32_t)) == 0);
const size_t n_words = size / sizeof(uint32_t);
for (size_t i = 0; i < n_words / 2; ++i) {
uint32_t left = __builtin_bswap32(response[i]);
uint32_t right = __builtin_bswap32(response[n_words - i - 1]);
response[i] = right;
response[n_words - i - 1] = left;
}
}
void sdmmc_card_print_info(FILE* stream, const sdmmc_card_t* card)
{
// bool print_scr = false;
// bool print_csd = false;
// const char* type;
// fprintf(stream, "Name: %s\n", card->cid.name);
// if (card->is_sdio) {
// type = "SDIO";
// print_scr = true;
// print_csd = true;
// } else if (card->is_mmc) {
// type = "MMC";
// print_csd = true;
// } else {
// type = (card->ocr & SD_OCR_SDHC_CAP) ? "SDHC/SDXC" : "SDSC";
// }
// fprintf(stream, "Type: %s\n", type);
// if (card->max_freq_khz < 1000) {
// fprintf(stream, "Speed: %d kHz\n", card->max_freq_khz);
// } else {
// fprintf(stream, "Speed: %d MHz%s\n", card->max_freq_khz / 1000,
// card->is_ddr ? ", DDR" : "");
// }
// fprintf(stream, "Size: %luMB\n", ((uint64_t) card->csd.capacity) * card->csd.sector_size / (1024 * 1024));
// if (print_csd) {
// fprintf(stream, "CSD: ver=%d, sector_size=%d, capacity=%d read_bl_len=%d\n",
// card->csd.csd_ver,
// card->csd.sector_size, card->csd.capacity, card->csd.read_block_len);
// }
// if (print_scr) {
// fprintf(stream, "SCR: sd_spec=%d, bus_width=%d\n", card->scr.sd_spec, card->scr.bus_width);
// }
}
sdmmc_err_t sdmmc_fix_host_flags(sdmmc_card_t* card)
{
const uint32_t width_1bit = SDMMC_HOST_FLAG_1BIT;
const uint32_t width_4bit = SDMMC_HOST_FLAG_4BIT;
const uint32_t width_8bit = SDMMC_HOST_FLAG_8BIT;
const uint32_t width_mask = width_1bit | width_4bit | width_8bit;
int slot_bit_width = card->host.get_bus_width(card->host.slot);
if (slot_bit_width == 1 &&
(card->host.flags & (width_4bit | width_8bit))) {
card->host.flags &= ~width_mask;
card->host.flags |= width_1bit;
} else if (slot_bit_width == 4 && (card->host.flags & width_8bit)) {
if ((card->host.flags & width_4bit) == 0) {
ESP_LOGW(TAG, "slot width set to 4, but host flags don't have 4 line mode enabled; using 1 line mode");
card->host.flags &= ~width_mask;
card->host.flags |= width_1bit;
} else {
card->host.flags &= ~width_mask;
card->host.flags |= width_4bit;
}
}
return SDMMC_OK;
}

132
lib/sdmmc/sdmmc_common.h Normal file
View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
* Adaptations to ESP-IDF Copyright (c) 2016-2018 Espressif Systems (Shanghai) PTE LTD
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include <string.h>
#include "sdmmc_defs.h"
#include "sdmmc_types.h"
#include "sdmmc_cmd.h"
#define SDMMC_GO_IDLE_DELAY_MS 20
#define SDMMC_IO_SEND_OP_COND_DELAY_MS 10
/* These delay values are mostly useful for cases when CD pin is not used, and
* the card is removed. In this case, SDMMC peripheral may not always return
* CMD_DONE / DATA_DONE interrupts after signaling the error. These timeouts work
* as a safety net in such cases.
*/
#define SDMMC_DEFAULT_CMD_TIMEOUT_MS 1000 // Max timeout of ordinary commands
#define SDMMC_WRITE_CMD_TIMEOUT_MS 5000 // Max timeout of write commands
/* Maximum retry/error count for SEND_OP_COND (CMD1).
* These are somewhat arbitrary, values originate from OpenBSD driver.
*/
#define SDMMC_SEND_OP_COND_MAX_RETRIES 100
#define SDMMC_SEND_OP_COND_MAX_ERRORS 3
/* Functions to send individual commands */
sdmmc_err_t sdmmc_send_cmd(sdmmc_card_t* card, sdmmc_command_t* cmd);
sdmmc_err_t sdmmc_send_app_cmd(sdmmc_card_t* card, sdmmc_command_t* cmd);
sdmmc_err_t sdmmc_send_cmd_go_idle_state(sdmmc_card_t* card);
sdmmc_err_t sdmmc_send_cmd_send_if_cond(sdmmc_card_t* card, uint32_t ocr);
sdmmc_err_t sdmmc_send_cmd_send_op_cond(sdmmc_card_t* card, uint32_t ocr, uint32_t *ocrp);
sdmmc_err_t sdmmc_send_cmd_read_ocr(sdmmc_card_t *card, uint32_t *ocrp);
sdmmc_err_t sdmmc_send_cmd_send_cid(sdmmc_card_t *card, sdmmc_cid_t *out_cid);
sdmmc_err_t sdmmc_send_cmd_all_send_cid(sdmmc_card_t* card, sdmmc_response_t* out_raw_cid);
sdmmc_err_t sdmmc_send_cmd_set_relative_addr(sdmmc_card_t* card, uint16_t* out_rca);
sdmmc_err_t sdmmc_send_cmd_set_blocklen(sdmmc_card_t* card, sdmmc_csd_t* csd);
sdmmc_err_t sdmmc_send_cmd_switch_func(sdmmc_card_t* card,
uint32_t mode, uint32_t group, uint32_t function,
sdmmc_switch_func_rsp_t* resp);
sdmmc_err_t sdmmc_send_cmd_send_csd(sdmmc_card_t* card, sdmmc_csd_t* out_csd);
sdmmc_err_t sdmmc_send_cmd_select_card(sdmmc_card_t* card, uint32_t rca);
sdmmc_err_t sdmmc_send_cmd_send_scr(sdmmc_card_t* card, sdmmc_scr_t *out_scr);
sdmmc_err_t sdmmc_send_cmd_set_bus_width(sdmmc_card_t* card, int width);
sdmmc_err_t sdmmc_send_cmd_send_status(sdmmc_card_t* card, uint32_t* out_status);
sdmmc_err_t sdmmc_send_cmd_crc_on_off(sdmmc_card_t* card, bool crc_enable);
/* Higher level functions */
sdmmc_err_t sdmmc_enable_hs_mode(sdmmc_card_t* card);
sdmmc_err_t sdmmc_enable_hs_mode_and_check(sdmmc_card_t* card);
sdmmc_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src,
size_t start_block, size_t block_count);
sdmmc_err_t sdmmc_read_sectors_dma(sdmmc_card_t* card, void* dst,
size_t start_block, size_t block_count);
/* SD specific */
sdmmc_err_t sdmmc_check_scr(sdmmc_card_t* card);
sdmmc_err_t sdmmc_decode_cid(sdmmc_response_t resp, sdmmc_cid_t* out_cid);
sdmmc_err_t sdmmc_decode_csd(sdmmc_response_t response, sdmmc_csd_t* out_csd);
sdmmc_err_t sdmmc_decode_scr(uint32_t *raw_scr, sdmmc_scr_t* out_scr);
/* SDIO specific */
sdmmc_err_t sdmmc_io_reset(sdmmc_card_t* card);
sdmmc_err_t sdmmc_io_enable_hs_mode(sdmmc_card_t* card);
sdmmc_err_t sdmmc_io_send_op_cond(sdmmc_card_t* card, uint32_t ocr, uint32_t *ocrp);
sdmmc_err_t sdmmc_io_rw_direct(sdmmc_card_t* card, int function,
uint32_t reg, uint32_t arg, uint8_t *byte);
sdmmc_err_t sdmmc_io_rw_extended(sdmmc_card_t* card, int function,
uint32_t reg, int arg, void *data, size_t size);
/* MMC specific */
sdmmc_err_t sdmmc_mmc_send_ext_csd_data(sdmmc_card_t* card, void *out_data, size_t datalen);
sdmmc_err_t sdmmc_mmc_switch(sdmmc_card_t* card, uint8_t set, uint8_t index, uint8_t value);
sdmmc_err_t sdmmc_mmc_decode_cid(int mmc_ver, sdmmc_response_t resp, sdmmc_cid_t* out_cid);
sdmmc_err_t sdmmc_mmc_decode_csd(sdmmc_response_t response, sdmmc_csd_t* out_csd);
sdmmc_err_t sdmmc_mmc_enable_hs_mode(sdmmc_card_t* card);
/* Parts of card initialization flow */
sdmmc_err_t sdmmc_init_sd_if_cond(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_select_card(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_csd(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_cid(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_rca(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_mmc_decode_cid(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_ocr(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_spi_crc(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_io(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_sd_blocklen(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_sd_scr(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_sd_wait_data_ready(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_mmc_read_ext_csd(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_mmc_read_cid(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_host_bus_width(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_sd_bus_width(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_io_bus_width(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_mmc_bus_width(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_card_hs_mode(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_host_frequency(sdmmc_card_t* card);
sdmmc_err_t sdmmc_init_mmc_check_csd(sdmmc_card_t* card);
/* Various helper functions */
static inline bool host_is_spi(const sdmmc_card_t* card)
{
return (card->host.flags & SDMMC_HOST_FLAG_SPI) != 0;
}
static inline uint32_t get_host_ocr(float voltage)
{
// TODO: report exact voltage to the card
// For now tell that the host has 2.8-3.6V voltage range
(void) voltage;
return SD_OCR_VOL_MASK;
}
void sdmmc_flip_byte_order(uint32_t* response, size_t size);
sdmmc_err_t sdmmc_fix_host_flags(sdmmc_card_t* card);

123
lib/sdmmc/sdmmc_init.c Normal file
View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
* Adaptations to ESP-IDF Copyright (c) 2016-2018 Espressif Systems (Shanghai) PTE LTD
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "sdmmc_common.h"
#define SDMMC_INIT_STEP(condition, function) \
do { \
if ((condition)) { \
sdmmc_err_t err = (function)(card); \
if (err != SDMMC_OK) { \
ESP_LOGD(TAG, "%s: %s returned 0x%x", __func__, #function, err); \
return err; \
} \
} \
} while(0);
sdmmc_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card)
{
memset(card, 0, sizeof(*card));
memcpy(&card->host, config, sizeof(*config));
const bool is_spi = host_is_spi(card);
const bool always = true;
const bool io_supported = true;
/* Check if host flags are compatible with slot configuration. */
SDMMC_INIT_STEP(!is_spi, sdmmc_fix_host_flags);
/* Reset SDIO (CMD52, RES) before re-initializing IO (CMD5). */
SDMMC_INIT_STEP(io_supported, sdmmc_io_reset);
/* GO_IDLE_STATE (CMD0) command resets the card */
SDMMC_INIT_STEP(always, sdmmc_send_cmd_go_idle_state);
/* SEND_IF_COND (CMD8) command is used to identify SDHC/SDXC cards. */
SDMMC_INIT_STEP(always, sdmmc_init_sd_if_cond);
/* IO_SEND_OP_COND(CMD5), Determine if the card is an IO card. */
SDMMC_INIT_STEP(io_supported, sdmmc_init_io);
const bool is_mem = card->is_mem;
const bool is_sdio = !is_mem;
/* Enable CRC16 checks for data transfers in SPI mode */
SDMMC_INIT_STEP(is_spi, sdmmc_init_spi_crc);
/* Use SEND_OP_COND to set up card OCR */
SDMMC_INIT_STEP(is_mem, sdmmc_init_ocr);
const bool is_mmc = is_mem && card->is_mmc;
const bool is_sdmem = is_mem && !is_mmc;
ESP_LOGD(TAG, "%s: card type is %s", __func__,
is_sdio ? "SDIO" : is_mmc ? "MMC" : "SD");
/* Read the contents of CID register*/
SDMMC_INIT_STEP(is_mem, sdmmc_init_cid);
/* Assign RCA */
SDMMC_INIT_STEP(!is_spi, sdmmc_init_rca);
/* Read and decode the contents of CSD register */
SDMMC_INIT_STEP(is_mem, sdmmc_init_csd);
/* Decode the contents of mmc CID register */
SDMMC_INIT_STEP(is_mmc && !is_spi, sdmmc_init_mmc_decode_cid);
/* Switch the card from stand-by mode to data transfer mode (not needed if
* SPI interface is used). This is needed to issue SET_BLOCKLEN and
* SEND_SCR commands.
*/
SDMMC_INIT_STEP(!is_spi, sdmmc_init_select_card);
/* SD memory cards:
* Set block len for SDSC cards to 512 bytes (same as SDHC)
* Read SCR
* Wait to enter data transfer state
*/
SDMMC_INIT_STEP(is_sdmem, sdmmc_init_sd_blocklen);
SDMMC_INIT_STEP(is_sdmem, sdmmc_init_sd_scr);
SDMMC_INIT_STEP(is_sdmem, sdmmc_init_sd_wait_data_ready);
/* MMC cards: read CXD */
SDMMC_INIT_STEP(is_mmc, sdmmc_init_mmc_read_ext_csd);
/* Try to switch card to HS mode if the card supports it.
* Set card->max_freq_khz value accordingly.
*/
SDMMC_INIT_STEP(always, sdmmc_init_card_hs_mode);
/* Set bus width. One call for every kind of card, then one for the host */
if (!is_spi) {
SDMMC_INIT_STEP(is_sdmem, sdmmc_init_sd_bus_width);
SDMMC_INIT_STEP(is_sdio, sdmmc_init_io_bus_width);
SDMMC_INIT_STEP(is_mmc, sdmmc_init_mmc_bus_width);
SDMMC_INIT_STEP(always, sdmmc_init_host_bus_width);
}
/* Switch to the host to use card->max_freq_khz frequency. */
SDMMC_INIT_STEP(always, sdmmc_init_host_frequency);
/* Sanity check after switching the bus mode and frequency */
SDMMC_INIT_STEP(is_sdmem, sdmmc_check_scr);
/* TODO: this is CMD line only, add data checks for eMMC */
SDMMC_INIT_STEP(is_mmc, sdmmc_init_mmc_check_csd);
/* TODO: add similar checks for SDIO */
return SDMMC_OK;
}

633
lib/sdmmc/sdmmc_io.c Normal file
View File

@ -0,0 +1,633 @@
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
* Adaptations to ESP-IDF Copyright (c) 2016-2018 Espressif Systems (Shanghai) PTE LTD
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
#include "sdmmc_common.h"
#define CIS_TUPLE(NAME) (cis_tuple_t) {.code=CISTPL_CODE_##NAME, .name=#NAME, .func=&cis_tuple_func_default, }
#define CIS_TUPLE_WITH_FUNC(NAME, FUNC) (cis_tuple_t) {.code=CISTPL_CODE_##NAME, .name=#NAME, .func=&(FUNC), }
#define CIS_CHECK_SIZE(SIZE, MINIMAL) do {int store_size = (SIZE); if((store_size) < (MINIMAL)) return SDMMC_ERR_INVALID_SIZE;} while(0)
#define CIS_CHECK_UNSUPPORTED(COND) do {if(!(COND)) return SDMMC_ERR_NOT_SUPPORTED;} while(0)
#define CIS_GET_MINIMAL_SIZE 32
typedef sdmmc_err_t (*cis_tuple_info_func_t)(const void* tuple_info, uint8_t* data, FILE* fp);
typedef struct {
int code;
const char *name;
cis_tuple_info_func_t func;
} cis_tuple_t;
static sdmmc_err_t cis_tuple_func_default(const void* p, uint8_t* data, FILE* fp);
static sdmmc_err_t cis_tuple_func_manfid(const void* p, uint8_t* data, FILE* fp);
static sdmmc_err_t cis_tuple_func_cftable_entry(const void* p, uint8_t* data, FILE* fp);
static sdmmc_err_t cis_tuple_func_end(const void* p, uint8_t* data, FILE* fp);
static const cis_tuple_t cis_table[] = {
CIS_TUPLE(NULL),
CIS_TUPLE(DEVICE),
CIS_TUPLE(CHKSUM),
CIS_TUPLE(VERS1),
CIS_TUPLE(ALTSTR),
CIS_TUPLE(CONFIG),
CIS_TUPLE_WITH_FUNC(CFTABLE_ENTRY, cis_tuple_func_cftable_entry),
CIS_TUPLE_WITH_FUNC(MANFID, cis_tuple_func_manfid),
CIS_TUPLE(FUNCID),
CIS_TUPLE(FUNCE),
CIS_TUPLE(VENDER_BEGIN),
CIS_TUPLE(VENDER_END),
CIS_TUPLE(SDIO_STD),
CIS_TUPLE(SDIO_EXT),
CIS_TUPLE_WITH_FUNC(END, cis_tuple_func_end),
};
sdmmc_err_t sdmmc_io_reset(sdmmc_card_t* card)
{
uint8_t sdio_reset = CCCR_CTL_RES;
sdmmc_err_t err = sdmmc_io_rw_direct(card, 0, SD_IO_CCCR_CTL, SD_ARG_CMD52_WRITE, &sdio_reset);
if (err == SDMMC_ERR_TIMEOUT || (host_is_spi(card) && err == SDMMC_ERR_NOT_SUPPORTED)) {
/* Non-IO cards are allowed to time out (in SD mode) or
* return "invalid command" error (in SPI mode).
*/
} else if (err == SDMMC_ERR_NO_CARD) {
ESP_LOGD(TAG, "%s: card not present", __func__);
return err;
} else if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: unexpected return: 0x%x", __func__, err );
return err;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_init_io(sdmmc_card_t* card)
{
/* IO_SEND_OP_COND(CMD5), Determine if the card is an IO card.
* Non-IO cards will not respond to this command.
*/
sdmmc_err_t err = sdmmc_io_send_op_cond(card, 0, &card->ocr);
if (err != SDMMC_OK) {
ESP_LOGD(TAG, "%s: io_send_op_cond (1) returned 0x%x; not IO card", __func__, err);
card->is_sdio = 0;
card->is_mem = 1;
} else {
card->is_sdio = 1;
if (card->ocr & SD_IO_OCR_MEM_PRESENT) {
ESP_LOGD(TAG, "%s: IO-only card", __func__);
card->is_mem = 0;
}
card->num_io_functions = SD_IO_OCR_NUM_FUNCTIONS(card->ocr);
ESP_LOGD(TAG, "%s: number of IO functions: %d", __func__, card->num_io_functions);
if (card->num_io_functions == 0) {
card->is_sdio = 0;
}
uint32_t host_ocr = get_host_ocr(card->host.io_voltage);
host_ocr &= card->ocr;
err = sdmmc_io_send_op_cond(card, host_ocr, &card->ocr);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: sdmmc_io_send_op_cond (1) returned 0x%x", __func__, err);
return err;
}
err = sdmmc_io_enable_int(card);
if (err != SDMMC_OK) {
ESP_LOGD(TAG, "%s: sdmmc_enable_int failed (0x%x)", __func__, err);
}
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_init_io_bus_width(sdmmc_card_t* card)
{
sdmmc_err_t err;
card->log_bus_width = 0;
if (card->host.flags & SDMMC_HOST_FLAG_4BIT) {
uint8_t card_cap = 0;
err = sdmmc_io_rw_direct(card, 0, SD_IO_CCCR_CARD_CAP,
SD_ARG_CMD52_READ, &card_cap);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: sdmmc_io_rw_direct (read SD_IO_CCCR_CARD_CAP) returned 0x%0x", __func__, err);
return err;
}
ESP_LOGD(TAG, "IO card capabilities byte: %02x", card_cap);
if (!(card_cap & CCCR_CARD_CAP_LSC) ||
(card_cap & CCCR_CARD_CAP_4BLS)) {
// This card supports 4-bit bus mode
uint8_t bus_width = CCCR_BUS_WIDTH_4;
err = sdmmc_io_rw_direct(card, 0, SD_IO_CCCR_BUS_WIDTH,
SD_ARG_CMD52_WRITE, &bus_width);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: sdmmc_io_rw_direct (write SD_IO_CCCR_BUS_WIDTH) returned 0x%0x", __func__, err);
return err;
}
card->log_bus_width = 2;
}
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_io_enable_hs_mode(sdmmc_card_t* card)
{
/* If the host is configured to use low frequency, don't attempt to switch */
if (card->host.max_freq_khz < SDMMC_FREQ_DEFAULT) {
card->max_freq_khz = card->host.max_freq_khz;
return SDMMC_OK;
} else if (card->host.max_freq_khz < SDMMC_FREQ_HIGHSPEED) {
card->max_freq_khz = SDMMC_FREQ_DEFAULT;
return SDMMC_OK;
}
/* For IO cards, do write + read operation on "High Speed" register,
* setting EHS bit. If both EHS and SHS read back as set, then HS mode
* has been enabled.
*/
uint8_t val = CCCR_HIGHSPEED_ENABLE;
sdmmc_err_t err = sdmmc_io_rw_direct(card, 0, SD_IO_CCCR_HIGHSPEED,
SD_ARG_CMD52_WRITE | SD_ARG_CMD52_EXCHANGE, &val);
if (err != SDMMC_OK) {
ESP_LOGD(TAG, "%s: sdmmc_io_rw_direct returned 0x%x", __func__, err);
return err;
}
ESP_LOGD(TAG, "%s: CCCR_HIGHSPEED=0x%02x", __func__, val);
const uint8_t hs_mask = CCCR_HIGHSPEED_ENABLE | CCCR_HIGHSPEED_SUPPORT;
if ((val & hs_mask) != hs_mask) {
return SDMMC_ERR_NOT_SUPPORTED;
}
card->max_freq_khz = SDMMC_FREQ_HIGHSPEED;
return SDMMC_OK;
}
sdmmc_err_t sdmmc_io_send_op_cond(sdmmc_card_t* card, uint32_t ocr, uint32_t *ocrp)
{
sdmmc_err_t err = SDMMC_OK;
sdmmc_command_t cmd = {
.flags = SCF_CMD_BCR | SCF_RSP_R4,
.arg = ocr,
.opcode = SD_IO_SEND_OP_COND
};
for (size_t i = 0; i < 100; i++) {
err = sdmmc_send_cmd(card, &cmd);
if (err != SDMMC_OK) {
break;
}
if ((MMC_R4(cmd.response) & SD_IO_OCR_MEM_READY) ||
ocr == 0) {
break;
}
err = SDMMC_ERR_TIMEOUT;
osal_task_delay(SDMMC_IO_SEND_OP_COND_DELAY_MS);
}
if (err == SDMMC_OK && ocrp != NULL)
*ocrp = MMC_R4(cmd.response);
return err;
}
sdmmc_err_t sdmmc_io_rw_direct(sdmmc_card_t* card, int func,
uint32_t reg, uint32_t arg, uint8_t *data)
{
sdmmc_err_t err;
sdmmc_command_t cmd = {
.flags = SCF_CMD_AC | SCF_RSP_R5,
.arg = 0,
.opcode = SD_IO_RW_DIRECT
};
arg |= (func & SD_ARG_CMD52_FUNC_MASK) << SD_ARG_CMD52_FUNC_SHIFT;
arg |= (reg & SD_ARG_CMD52_REG_MASK) << SD_ARG_CMD52_REG_SHIFT;
arg |= (*data & SD_ARG_CMD52_DATA_MASK) << SD_ARG_CMD52_DATA_SHIFT;
cmd.arg = arg;
err = sdmmc_send_cmd(card, &cmd);
if (err != SDMMC_OK) {
ESP_LOGV(TAG, "%s: sdmmc_send_cmd returned 0x%x", __func__, err);
return err;
}
*data = SD_R5_DATA(cmd.response);
return SDMMC_OK;
}
sdmmc_err_t sdmmc_io_read_byte(sdmmc_card_t* card, uint32_t function,
uint32_t addr, uint8_t *out_byte)
{
sdmmc_err_t ret = sdmmc_io_rw_direct(card, function, addr, SD_ARG_CMD52_READ, out_byte);
if (ret != SDMMC_OK) {
ESP_LOGE(TAG, "%s: sdmmc_io_rw_direct (read 0x%x) returned 0x%x", __func__, addr, ret);
}
return ret;
}
sdmmc_err_t sdmmc_io_write_byte(sdmmc_card_t* card, uint32_t function,
uint32_t addr, uint8_t in_byte, uint8_t* out_byte)
{
uint8_t tmp_byte = in_byte;
sdmmc_err_t ret = sdmmc_io_rw_direct(card, function, addr,
SD_ARG_CMD52_WRITE | SD_ARG_CMD52_EXCHANGE, &tmp_byte);
if (ret != SDMMC_OK) {
ESP_LOGE(TAG, "%s: sdmmc_io_rw_direct (write 0x%x) returned 0x%x", __func__, addr, ret);
return ret;
}
if (out_byte != NULL) {
*out_byte = tmp_byte;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_io_rw_extended(sdmmc_card_t* card, int func,
uint32_t reg, int arg, void *datap, size_t datalen)
{
sdmmc_err_t err;
const size_t max_byte_transfer_size = 512;
sdmmc_command_t cmd = {
.flags = SCF_CMD_AC | SCF_RSP_R5,
.arg = 0,
.opcode = SD_IO_RW_EXTENDED,
.data = datap,
.datalen = datalen,
.blklen = max_byte_transfer_size /* TODO: read max block size from CIS */
};
uint32_t count; /* number of bytes or blocks, depending on transfer mode */
if (arg & SD_ARG_CMD53_BLOCK_MODE) {
if (cmd.datalen % cmd.blklen != 0) {
return SDMMC_ERR_INVALID_SIZE;
}
count = cmd.datalen / cmd.blklen;
} else {
if (datalen > max_byte_transfer_size) {
/* TODO: split into multiple operations? */
return SDMMC_ERR_INVALID_SIZE;
}
if (datalen == max_byte_transfer_size) {
count = 0; // See 5.3.1 SDIO simplifed spec
} else {
count = datalen;
}
cmd.blklen = datalen;
}
arg |= (func & SD_ARG_CMD53_FUNC_MASK) << SD_ARG_CMD53_FUNC_SHIFT;
arg |= (reg & SD_ARG_CMD53_REG_MASK) << SD_ARG_CMD53_REG_SHIFT;
arg |= (count & SD_ARG_CMD53_LENGTH_MASK) << SD_ARG_CMD53_LENGTH_SHIFT;
cmd.arg = arg;
if ((arg & SD_ARG_CMD53_WRITE) == 0) {
cmd.flags |= SCF_CMD_READ;
}
err = sdmmc_send_cmd(card, &cmd);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x", __func__, err);
return err;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_io_read_bytes(sdmmc_card_t* card, uint32_t function,
uint32_t addr, void* dst, size_t size)
{
/* host quirk: SDIO transfer with length not divisible by 4 bytes
* has to be split into two transfers: one with aligned length,
* the other one for the remaining 1-3 bytes.
*/
uint8_t *pc_dst = dst;
while (size > 0) {
size_t size_aligned = size & (~3);
size_t will_transfer = size_aligned > 0 ? size_aligned : size;
sdmmc_err_t err = sdmmc_io_rw_extended(card, function, addr,
SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT,
pc_dst, will_transfer);
if (err != SDMMC_OK) {
return err;
}
pc_dst += will_transfer;
size -= will_transfer;
addr += will_transfer;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_io_write_bytes(sdmmc_card_t* card, uint32_t function,
uint32_t addr, const void* src, size_t size)
{
/* same host quirk as in sdmmc_io_read_bytes */
const uint8_t *pc_src = (const uint8_t*) src;
while (size > 0) {
size_t size_aligned = size & (~3);
size_t will_transfer = size_aligned > 0 ? size_aligned : size;
sdmmc_err_t err = sdmmc_io_rw_extended(card, function, addr,
SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT,
(void*) pc_src, will_transfer);
if (err != SDMMC_OK) {
return err;
}
pc_src += will_transfer;
size -= will_transfer;
addr += will_transfer;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_io_read_blocks(sdmmc_card_t* card, uint32_t function,
uint32_t addr, void* dst, size_t size)
{
if (size % 4 != 0) {
return SDMMC_ERR_INVALID_SIZE;
}
return sdmmc_io_rw_extended(card, function, addr,
SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT | SD_ARG_CMD53_BLOCK_MODE,
dst, size);
}
sdmmc_err_t sdmmc_io_write_blocks(sdmmc_card_t* card, uint32_t function,
uint32_t addr, const void* src, size_t size)
{
if (size % 4 != 0) {
return SDMMC_ERR_INVALID_SIZE;
}
return sdmmc_io_rw_extended(card, function, addr,
SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT | SD_ARG_CMD53_BLOCK_MODE,
(void*) src, size);
}
sdmmc_err_t sdmmc_io_enable_int(sdmmc_card_t* card)
{
if (card->host.io_int_enable == NULL) {
return SDMMC_ERR_NOT_SUPPORTED;
}
return (*card->host.io_int_enable)(card->host.slot);
}
sdmmc_err_t sdmmc_io_wait_int(sdmmc_card_t* card, int timeout_ms)
{
if (card->host.io_int_wait == NULL) {
return SDMMC_ERR_NOT_SUPPORTED;
}
return (*card->host.io_int_wait)(card->host.slot, timeout_ms);
}
/*
* Print the CIS information of a CIS card, currently only ESP slave supported.
*/
static sdmmc_err_t cis_tuple_func_default(const void* p, uint8_t* data, FILE* fp)
{
const cis_tuple_t* tuple = (const cis_tuple_t*)p;
uint8_t code = *(data++);
int size = *(data++);
if (tuple) {
fprintf(fp, "TUPLE: %s, size: %d: ", tuple->name, size);
} else {
fprintf(fp, "TUPLE: unknown(%02X), size: %d: ", code, size);
}
for (int i = 0; i < size; i++) fprintf(fp, "%02X ", *(data++));
fprintf(fp, "\n");
return SDMMC_OK;
}
static sdmmc_err_t cis_tuple_func_manfid(const void* p, uint8_t* data, FILE* fp)
{
const cis_tuple_t* tuple = (const cis_tuple_t*)p;
data++;
int size = *(data++);
fprintf(fp, "TUPLE: %s, size: %d\n", tuple->name, size);
CIS_CHECK_SIZE(size, 4);
fprintf(fp, " MANF: %04X, CARD: %04X\n", *(uint16_t*)(data), *(uint16_t*)(data+2));
return SDMMC_OK;
}
static sdmmc_err_t cis_tuple_func_end(const void* p, uint8_t* data, FILE* fp)
{
const cis_tuple_t* tuple = (const cis_tuple_t*)p;
data++;
fprintf(fp, "TUPLE: %s\n", tuple->name);
return SDMMC_OK;
}
static sdmmc_err_t cis_tuple_func_cftable_entry(const void* p, uint8_t* data, FILE* fp)
{
const cis_tuple_t* tuple = (const cis_tuple_t*)p;
data++;
int size = *(data++);
fprintf(fp, "TUPLE: %s, size: %d\n", tuple->name, size);
CIS_CHECK_SIZE(size, 2);
CIS_CHECK_SIZE(size--, 1);
bool interface = data[0] & BIT(7);
bool def = data[0] & BIT(6);
int conf_ent_num = data[0] & 0x3F;
fprintf(fp, " INDX: %02X, Intface: %d, Default: %d, Conf-Entry-Num: %d\n", *(data++), interface, def, conf_ent_num);
if (interface) {
CIS_CHECK_SIZE(size--, 1);
fprintf(fp, " IF: %02X\n", *(data++));
}
CIS_CHECK_SIZE(size--, 1);
bool misc = data[0] & BIT(7);
int mem_space = (data[0] >> 5 )&(0x3);
bool irq = data[0] & BIT(4);
bool io_sp = data[0] & BIT(3);
bool timing = data[0] & BIT(2);
int power = data[0] & 3;
fprintf(fp, " FS: %02X, misc: %d, mem_space: %d, irq: %d, io_space: %d, timing: %d, power: %d\n", *(data++), misc, mem_space, irq, io_sp, timing, power);
CIS_CHECK_UNSUPPORTED(power == 0); //power descriptor is not handled yet
CIS_CHECK_UNSUPPORTED(!timing); //timing descriptor is not handled yet
CIS_CHECK_UNSUPPORTED(!io_sp); //io space descriptor is not handled yet
if (irq) {
CIS_CHECK_SIZE(size--, 1);
bool mask = data[0] & BIT(4);
fprintf(fp, " IR: %02X, mask: %d, ",*(data++), mask);
if (mask) {
CIS_CHECK_SIZE(size, 2);
size-=2;
fprintf(fp, " IRQ: %02X %02X\n", data[0], data[1]);
data+=2;
}
}
if (mem_space) {
CIS_CHECK_SIZE(size, 2);
size-=2;
CIS_CHECK_UNSUPPORTED(mem_space==1); //other cases not handled yet
int len = *(uint16_t*)data;
fprintf(fp, " LEN: %04X\n", len);
data+=2;
}
CIS_CHECK_UNSUPPORTED(misc==0); //misc descriptor is not handled yet
return SDMMC_OK;
}
static const cis_tuple_t* get_tuple(uint8_t code)
{
for (size_t i = 0; i < sizeof(cis_table)/sizeof(cis_tuple_t); i++) {
if (code == cis_table[i].code) return &cis_table[i];
}
return NULL;
}
sdmmc_err_t sdmmc_io_print_cis_info(uint8_t* buffer, size_t buffer_size, FILE* fp)
{
if (!fp) fp = stdout;
uint8_t* cis = buffer;
do {
const cis_tuple_t* tuple = get_tuple(cis[0]);
int size = cis[1];
sdmmc_err_t ret = SDMMC_OK;
if (tuple) {
ret = tuple->func(tuple, cis, fp);
} else {
ret = cis_tuple_func_default(NULL, cis, fp);
}
if (ret != SDMMC_OK) return ret;
cis += 2 + size;
if (tuple && tuple->code == CISTPL_CODE_END) break;
} while (cis < buffer + buffer_size) ;
return SDMMC_OK;
}
/**
* Check tuples in the buffer.
*
* @param buf Buffer to check
* @param buffer_size Size of the buffer
* @param inout_cis_offset
* - input: the last cis_offset, relative to the beginning of the buf. -1 if
* this buffer begin with the tuple length, otherwise should be no smaller than
* zero.
* - output: when the end tuple found, output offset of the CISTPL_CODE_END
* byte + 1 (relative to the beginning of the buffer; when not found, output
* the address of next tuple code.
*
* @return true if found, false if haven't.
*/
static bool check_tuples_in_buffer(uint8_t* buf, int buffer_size, int* inout_cis_offset)
{
int cis_offset = *inout_cis_offset;
if (cis_offset == -1) {
//the CIS code is checked in the last buffer, skip to next tuple
cis_offset += buf[0] + 2;
}
assert(cis_offset >= 0);
while (1) {
if (cis_offset < buffer_size) {
//A CIS code in the buffer, check it
if (buf[cis_offset] == CISTPL_CODE_END) {
*inout_cis_offset = cis_offset + 1;
return true;
}
}
if (cis_offset + 1 < buffer_size) {
cis_offset += buf[cis_offset+1] + 2;
} else {
break;
}
}
*inout_cis_offset = cis_offset;
return false;
}
sdmmc_err_t sdmmc_io_get_cis_data(sdmmc_card_t* card, uint8_t* out_buffer, size_t buffer_size, size_t* inout_cis_size)
{
sdmmc_err_t ret = SDMMC_OK;
uint32_t buf[CIS_GET_MINIMAL_SIZE / sizeof(uint32_t)];
/* Pointer to size is a mandatory parameter */
assert(inout_cis_size);
/*
* CIS region exist in 0x1000~0x17FFF of FUNC 0, get the start address of it
* from CCCR register.
*/
uint32_t addr;
ret = sdmmc_io_read_bytes(card, 0, 9, &addr, 3);
if (ret != SDMMC_OK) return ret;
//the sdmmc_io driver reads 4 bytes, the most significant byte is not the address.
addr &= 0xffffff;
if (addr < 0x1000 || addr > 0x17FFF) {
return SDMMC_ERR_INVALID_RESPONSE;
}
/*
* To avoid reading too long, take the input value as limitation if
* existing.
*/
size_t max_reading = UINT32_MAX;
if (*inout_cis_size != 0) {
max_reading = *inout_cis_size;
}
/*
* Parse the length while reading. If find the end tuple, or reaches the
* limitation, read no more and return both the data and the size already
* read.
*/
size_t buffer_offset = 0;
size_t cur_cis_offset = 0;
bool end_tuple_found = false;
do {
ret = sdmmc_io_read_bytes(card, 0, addr + buffer_offset, &buf, CIS_GET_MINIMAL_SIZE);
if (ret != SDMMC_OK) return ret;
//calculate relative to the beginning of the buffer
int offset = cur_cis_offset - buffer_offset;
bool finish = check_tuples_in_buffer((uint8_t*) buf, CIS_GET_MINIMAL_SIZE, &offset);
int remain_size = buffer_size - buffer_offset;
int copy_len;
if (finish) {
copy_len = TSD_MIN(offset, remain_size);
end_tuple_found = true;
} else {
copy_len = TSD_MIN(CIS_GET_MINIMAL_SIZE, remain_size);
}
if (copy_len > 0) {
memcpy(out_buffer + buffer_offset, buf, copy_len);
}
cur_cis_offset = buffer_offset + offset;
buffer_offset += CIS_GET_MINIMAL_SIZE;
} while (!end_tuple_found && buffer_offset < max_reading);
if (end_tuple_found) {
*inout_cis_size = cur_cis_offset;
if (cur_cis_offset > buffer_size) {
return SDMMC_ERR_INVALID_SIZE;
} else {
return SDMMC_OK;
}
} else {
return SDMMC_ERR_NO_CARD;
}
}

251
lib/sdmmc/sdmmc_mmc.c Normal file
View File

@ -0,0 +1,251 @@
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
* Adaptations to ESP-IDF Copyright (c) 2016-2018 Espressif Systems (Shanghai) PTE LTD
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
#include <unistd.h>
#include "sdmmc_common.h"
sdmmc_err_t sdmmc_init_mmc_read_ext_csd(sdmmc_card_t* card)
{
int card_type;
sdmmc_err_t err = SDMMC_OK;
uint32_t ext_csd[EXT_CSD_MMC_SIZE / sizeof(uint32_t)];
uint32_t sectors = 0;
ESP_LOGD(TAG, "MMC version: %d", card->csd.mmc_ver);
if (card->csd.mmc_ver < MMC_CSD_MMCVER_4_0) {
return SDMMC_ERR_NOT_SUPPORTED;
}
/* read EXT_CSD */
err = sdmmc_mmc_send_ext_csd_data(card, ext_csd, EXT_CSD_MMC_SIZE);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: send_ext_csd_data error 0x%x", __func__, err);
return err;
}
card_type = ext_csd[EXT_CSD_CARD_TYPE / sizeof(uint32_t)];
card->is_ddr = 0;
if (card_type & EXT_CSD_CARD_TYPE_F_52M_1_8V) {
card->max_freq_khz = SDMMC_FREQ_52M;
if ((card->host.flags & SDMMC_HOST_FLAG_DDR) &&
card->host.max_freq_khz >= SDMMC_FREQ_26M &&
card->host.get_bus_width(card->host.slot) == 4) {
ESP_LOGD(TAG, "card and host support DDR mode");
card->is_ddr = 1;
}
} else if (card_type & EXT_CSD_CARD_TYPE_F_52M) {
card->max_freq_khz = SDMMC_FREQ_52M;
} else if (card_type & EXT_CSD_CARD_TYPE_F_26M) {
card->max_freq_khz = SDMMC_FREQ_26M;
} else {
ESP_LOGW(TAG, "%s: unknown CARD_TYPE 0x%x", __func__, card_type);
}
/* For MMC cards, use speed value from EXT_CSD */
card->csd.tr_speed = card->max_freq_khz * 1000;
ESP_LOGD(TAG, "MMC card type %d, max_freq_khz=%d, is_ddr=%d", card_type, card->max_freq_khz, card->is_ddr);
card->max_freq_khz = TSD_MIN(card->max_freq_khz, card->host.max_freq_khz);
if (card->host.flags & SDMMC_HOST_FLAG_8BIT) {
card->ext_csd.power_class = ext_csd[((card->max_freq_khz > SDMMC_FREQ_26M) ?
EXT_CSD_PWR_CL_52_360 : EXT_CSD_PWR_CL_26_360) / sizeof(uint32_t)] >> 4;
card->log_bus_width = 3;
} else if (card->host.flags & SDMMC_HOST_FLAG_4BIT) {
card->ext_csd.power_class = ext_csd[((card->max_freq_khz > SDMMC_FREQ_26M) ?
EXT_CSD_PWR_CL_52_360 : EXT_CSD_PWR_CL_26_360) / sizeof(uint32_t)] & 0x0f;
card->log_bus_width = 2;
} else {
card->ext_csd.power_class = 0; //card must be able to do full rate at powerclass 0 in 1-bit mode
card->log_bus_width = 0;
}
sectors = ext_csd[EXT_CSD_SEC_COUNT / sizeof(uint32_t)];
if (sectors > (2u * 1024 * 1024 * 1024) / 512) {
card->csd.capacity = sectors;
}
return err;
}
sdmmc_err_t sdmmc_init_mmc_bus_width(sdmmc_card_t* card)
{
sdmmc_err_t err;
if (card->ext_csd.power_class != 0) {
err = sdmmc_mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_POWER_CLASS, card->ext_csd.power_class);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: can't change power class (%d bit), 0x%x"
, __func__, card->ext_csd.power_class, err);
return err;
}
}
if (card->log_bus_width > 0) {
int csd_bus_width_value = EXT_CSD_BUS_WIDTH_1;
int bus_width = 1;
if (card->log_bus_width == 2) {
if (card->is_ddr) {
csd_bus_width_value = EXT_CSD_BUS_WIDTH_4_DDR;
} else {
csd_bus_width_value = EXT_CSD_BUS_WIDTH_4;
}
bus_width = 4;
} else if (card->log_bus_width == 3) {
if (card->is_ddr) {
csd_bus_width_value = EXT_CSD_BUS_WIDTH_8_DDR;
} else {
csd_bus_width_value = EXT_CSD_BUS_WIDTH_8;
}
bus_width = 8;
}
err = sdmmc_mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH, csd_bus_width_value);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: can't change bus width (%d bit), 0x%x",
__func__, bus_width, err);
(void) bus_width;
return err;
}
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_mmc_enable_hs_mode(sdmmc_card_t* card)
{
sdmmc_err_t err;
if (card->max_freq_khz > SDMMC_FREQ_26M) {
/* switch to high speed timing */
err = sdmmc_mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, EXT_CSD_HS_TIMING_HS);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: mmc_switch EXT_CSD_HS_TIMING_HS error 0x%x",
__func__, err);
return err;
}
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_mmc_decode_cid(int mmc_ver, sdmmc_response_t resp, sdmmc_cid_t* out_cid)
{
if (mmc_ver == MMC_CSD_MMCVER_1_0 ||
mmc_ver == MMC_CSD_MMCVER_1_4) {
out_cid->mfg_id = MMC_CID_MID_V1(resp);
out_cid->oem_id = 0;
MMC_CID_PNM_V1_CPY(resp, out_cid->name);
out_cid->revision = MMC_CID_REV_V1(resp);
out_cid->serial = MMC_CID_PSN_V1(resp);
out_cid->date = MMC_CID_MDT_V1(resp);
} else if (mmc_ver == MMC_CSD_MMCVER_2_0 ||
mmc_ver == MMC_CSD_MMCVER_3_1 ||
mmc_ver == MMC_CSD_MMCVER_4_0) {
out_cid->mfg_id = MMC_CID_MID_V2(resp);
out_cid->oem_id = MMC_CID_OID_V2(resp);
MMC_CID_PNM_V1_CPY(resp, out_cid->name);
out_cid->revision = 0;
out_cid->serial = MMC_CID_PSN_V1(resp);
out_cid->date = 0;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_mmc_decode_csd(sdmmc_response_t response, sdmmc_csd_t* out_csd)
{
out_csd->csd_ver = MMC_CSD_CSDVER(response);
if (out_csd->csd_ver == MMC_CSD_CSDVER_1_0 ||
out_csd->csd_ver == MMC_CSD_CSDVER_2_0 ||
out_csd->csd_ver == MMC_CSD_CSDVER_EXT_CSD) {
out_csd->mmc_ver = MMC_CSD_MMCVER(response);
out_csd->capacity = MMC_CSD_CAPACITY(response);
out_csd->read_block_len = MMC_CSD_READ_BL_LEN(response);
} else {
ESP_LOGE(TAG, "unknown MMC CSD structure version 0x%x\n", out_csd->csd_ver);
return 1;
}
int read_bl_size = 1 << out_csd->read_block_len;
out_csd->sector_size = TSD_MIN(read_bl_size, 512);
if (out_csd->sector_size < read_bl_size) {
out_csd->capacity *= read_bl_size / out_csd->sector_size;
}
/* tr_speed will be determined when reading CXD */
out_csd->tr_speed = 0;
return SDMMC_OK;
}
sdmmc_err_t sdmmc_mmc_send_ext_csd_data(sdmmc_card_t* card, void *out_data, size_t datalen)
{
sdmmc_command_t cmd = {
.data = out_data,
.datalen = datalen,
.blklen = datalen,
.opcode = MMC_SEND_EXT_CSD,
.arg = 0,
.flags = SCF_CMD_ADTC | SCF_RSP_R1 | SCF_CMD_READ
};
return sdmmc_send_cmd(card, &cmd);
}
sdmmc_err_t sdmmc_mmc_switch(sdmmc_card_t* card, uint8_t set, uint8_t index, uint8_t value)
{
sdmmc_command_t cmd = {
.opcode = MMC_SWITCH,
.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | (index << 16) | (value << 8) | set,
.flags = SCF_RSP_R1B | SCF_CMD_AC | SCF_WAIT_BUSY,
};
sdmmc_err_t err = sdmmc_send_cmd(card, &cmd);
if (err == SDMMC_OK) {
//check response bit to see that switch was accepted
if (MMC_R1(cmd.response) & MMC_R1_SWITCH_ERROR)
err = SDMMC_ERR_INVALID_RESPONSE;
}
return err;
}
sdmmc_err_t sdmmc_init_mmc_check_csd(sdmmc_card_t* card)
{
sdmmc_err_t err;
assert(card->is_mem == 1);
assert(card->rca != 0);
//The card will not respond to send_csd command in the transfer state.
//Deselect it first.
err = sdmmc_send_cmd_select_card(card, 0);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: select_card returned 0x%x", __func__, err);
return err;
}
sdmmc_csd_t csd;
/* Get the contents of CSD register to verify the communication over CMD line
is OK. */
err = sdmmc_send_cmd_send_csd(card, &csd);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: send_csd returned 0x%x", __func__, err);
return err;
}
//Select the card again
err = sdmmc_send_cmd_select_card(card, card->rca);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: select_card returned 0x%x", __func__, err);
return err;
}
return SDMMC_OK;
}

343
lib/sdmmc/sdmmc_sd.c Normal file
View File

@ -0,0 +1,343 @@
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
* Adaptations to ESP-IDF Copyright (c) 2016-2018 Espressif Systems (Shanghai) PTE LTD
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
#include "sdmmc_common.h"
sdmmc_err_t sdmmc_init_sd_if_cond(sdmmc_card_t* card)
{
/* SEND_IF_COND (CMD8) command is used to identify SDHC/SDXC cards.
* SD v1 and non-SD cards will not respond to this command.
*/
uint32_t host_ocr = get_host_ocr(card->host.io_voltage);
sdmmc_err_t err = sdmmc_send_cmd_send_if_cond(card, host_ocr);
if (err == SDMMC_OK) {
ESP_LOGD(TAG, "SDHC/SDXC card");
host_ocr |= SD_OCR_SDHC_CAP;
} else if (err == SDMMC_ERR_TIMEOUT) {
ESP_LOGD(TAG, "CMD8 timeout; not an SD v2.00 card");
} else if (host_is_spi(card) && err == SDMMC_ERR_NOT_SUPPORTED) {
ESP_LOGD(TAG, "CMD8 rejected; not an SD v2.00 card");
} else {
ESP_LOGE(TAG, "%s: send_if_cond (1) returned 0x%x", __func__, err);
return err;
}
card->ocr = host_ocr;
return SDMMC_OK;
}
sdmmc_err_t sdmmc_init_sd_blocklen(sdmmc_card_t* card)
{
/* SDSC cards support configurable data block lengths.
* We don't use this feature and set the block length to 512 bytes,
* same as the block length for SDHC cards.
*/
if ((card->ocr & SD_OCR_SDHC_CAP) == 0) {
sdmmc_err_t err = sdmmc_send_cmd_set_blocklen(card, &card->csd);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: set_blocklen returned 0x%x", __func__, err);
return err;
}
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_init_sd_scr(sdmmc_card_t* card)
{
sdmmc_err_t err;
/* Get the contents of SCR register: bus width and the version of SD spec
* supported by the card.
* In SD mode, this is the first command which uses D0 line. Errors at
* this step usually indicate connection issue or lack of pull-up resistor.
*/
err = sdmmc_send_cmd_send_scr(card, &card->scr);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: send_scr (1) returned 0x%x", __func__, err);
return err;
}
if ((card->scr.bus_width & SCR_SD_BUS_WIDTHS_4BIT)
&& (card->host.flags & SDMMC_HOST_FLAG_4BIT)) {
card->log_bus_width = 2;
} else {
card->log_bus_width = 0;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_init_sd_bus_width(sdmmc_card_t* card)
{
int width = 1;
if (card->log_bus_width == 2) {
width = 4;
} else if (card->log_bus_width == 3) {
width = 8;
}
sdmmc_err_t err = sdmmc_send_cmd_set_bus_width(card, width);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "set_bus_width failed (0x%x)", err);
return err;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_init_sd_wait_data_ready(sdmmc_card_t* card)
{
/* Wait for the card to be ready for data transfers */
uint32_t status = 0;
uint32_t count = 0;
while (!host_is_spi(card) && !(status & MMC_R1_READY_FOR_DATA)) {
// TODO: add some timeout here
sdmmc_err_t err = sdmmc_send_cmd_send_status(card, &status);
if (err != SDMMC_OK) {
return err;
}
if (++count % 16 == 0) {
ESP_LOGV(TAG, "waiting for card to become ready (%d)", count);
}
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_send_cmd_switch_func(sdmmc_card_t* card,
uint32_t mode, uint32_t group, uint32_t function,
sdmmc_switch_func_rsp_t* resp)
{
if (card->scr.sd_spec < SCR_SD_SPEC_VER_1_10 ||
((card->csd.card_command_class & SD_CSD_CCC_SWITCH) == 0)) {
return SDMMC_ERR_NOT_SUPPORTED;
}
if (group == 0 ||
group > SD_SFUNC_GROUP_MAX ||
function > SD_SFUNC_FUNC_MAX) {
return SDMMC_ERR_INVALID_ARG;
}
if (mode > 1) {
return SDMMC_ERR_INVALID_ARG;
}
uint32_t group_shift = (group - 1) << 2;
/* all functions which should not be affected are set to 0xf (no change) */
uint32_t other_func_mask = (0x00ffffff & ~(0xf << group_shift));
uint32_t func_val = (function << group_shift) | other_func_mask;
sdmmc_command_t cmd = {
.opcode = MMC_SWITCH,
.flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1,
.blklen = sizeof(sdmmc_switch_func_rsp_t),
.data = resp->data,
.datalen = sizeof(sdmmc_switch_func_rsp_t),
.arg = (!!mode << 31) | func_val
};
sdmmc_err_t err = sdmmc_send_cmd(card, &cmd);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: sdmmc_send_cmd returned 0x%x", __func__, err);
return err;
}
sdmmc_flip_byte_order(resp->data, sizeof(sdmmc_switch_func_rsp_t));
uint32_t resp_ver = SD_SFUNC_VER(resp->data);
if (resp_ver == 0) {
/* busy response is never sent */
} else if (resp_ver == 1) {
if (SD_SFUNC_BUSY(resp->data, group) & (1 << function)) {
ESP_LOGD(TAG, "%s: response indicates function %d:%d is busy",
__func__, group, function);
return SDMMC_ERR_BUSY;
}
} else {
ESP_LOGD(TAG, "%s: got an invalid version of SWITCH_FUNC response: 0x%02x",
__func__, resp_ver);
return SDMMC_ERR_INVALID_RESPONSE;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_enable_hs_mode(sdmmc_card_t* card)
{
/* This will determine if the card supports SWITCH_FUNC command,
* and high speed mode. If the cards supports both, this will enable
* high speed mode at the card side.
*/
if (card->scr.sd_spec < SCR_SD_SPEC_VER_1_10 ||
((card->csd.card_command_class & SD_CSD_CCC_SWITCH) == 0)) {
return SDMMC_ERR_NOT_SUPPORTED;
}
sdmmc_switch_func_rsp_t response;
sdmmc_err_t err = sdmmc_send_cmd_switch_func(card, 0, SD_ACCESS_MODE, 0, &response);
if (err != SDMMC_OK) {
ESP_LOGD(TAG, "%s: sdmmc_send_cmd_switch_func (1) returned 0x%x", __func__, err);
return err;
}
uint32_t supported_mask = SD_SFUNC_SUPPORTED(response.data, 1);
if ((supported_mask & BIT(SD_ACCESS_MODE_SDR25)) == 0) {
return SDMMC_ERR_NOT_SUPPORTED;
}
err = sdmmc_send_cmd_switch_func(card, 1, SD_ACCESS_MODE, SD_ACCESS_MODE_SDR25, &response);
if (err != SDMMC_OK) {
ESP_LOGD(TAG, "%s: sdmmc_send_cmd_switch_func (2) returned 0x%x", __func__, err);
return err;
}
return err;
}
sdmmc_err_t sdmmc_enable_hs_mode_and_check(sdmmc_card_t* card)
{
/* All cards should support at least default speed */
card->max_freq_khz = SDMMC_FREQ_DEFAULT;
if (card->host.max_freq_khz <= card->max_freq_khz) {
/* Host is configured to use low frequency, don't attempt to switch */
card->max_freq_khz = card->host.max_freq_khz;
return SDMMC_OK;
}
/* Try to enabled HS mode */
sdmmc_err_t err = sdmmc_enable_hs_mode(card);
if (err != SDMMC_OK) {
return err;
}
/* HS mode has been enabled on the card.
* Read CSD again, it should now indicate that the card supports
* 50MHz clock.
* Since SEND_CSD is allowed only in standby mode, and the card is currently in data transfer
* mode, deselect the card first, then get the CSD, then select the card again. This step is
* not required in SPI mode, since CMD7 (select_card) is not supported.
*/
const bool is_spi = host_is_spi(card);
if (!is_spi) {
err = sdmmc_send_cmd_select_card(card, 0);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: select_card (1) returned 0x%x", __func__, err);
return err;
}
}
err = sdmmc_send_cmd_send_csd(card, &card->csd);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: send_csd returned 0x%x", __func__, err);
return err;
}
if (!is_spi) {
err = sdmmc_send_cmd_select_card(card, card->rca);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: select_card (2) returned 0x%x", __func__, err);
return err;
}
}
if (card->csd.tr_speed != 50000000) {
ESP_LOGW(TAG, "unexpected: after enabling HS mode, tr_speed=%d", card->csd.tr_speed);
return SDMMC_ERR_NOT_SUPPORTED;
}
card->max_freq_khz = SDMMC_FREQ_HIGHSPEED;
return SDMMC_OK;
}
sdmmc_err_t sdmmc_check_scr(sdmmc_card_t* card)
{
/* If frequency switch has been performed, read SCR register one more time
* and compare the result with the previous one. Use this simple check as
* an indicator of potential signal integrity issues.
*/
sdmmc_scr_t scr_tmp;
sdmmc_err_t err = sdmmc_send_cmd_send_scr(card, &scr_tmp);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: send_scr returned 0x%x", __func__, err);
return err;
}
if (memcmp(&card->scr, &scr_tmp, sizeof(scr_tmp)) != 0) {
ESP_LOGE(TAG, "got corrupted data after increasing clock frequency");
return SDMMC_ERR_INVALID_RESPONSE;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_init_spi_crc(sdmmc_card_t* card)
{
/* In SD mode, CRC checks of data transfers are mandatory and performed
* by the hardware. In SPI mode, CRC16 of data transfers is optional and
* needs to be enabled.
*/
assert(host_is_spi(card));
sdmmc_err_t err = sdmmc_send_cmd_crc_on_off(card, true);
if (err != SDMMC_OK) {
ESP_LOGE(TAG, "%s: sdmmc_send_cmd_crc_on_off returned 0x%x", __func__, err);
return err;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_decode_cid(sdmmc_response_t resp, sdmmc_cid_t* out_cid)
{
out_cid->mfg_id = SD_CID_MID(resp);
out_cid->oem_id = SD_CID_OID(resp);
SD_CID_PNM_CPY(resp, out_cid->name);
out_cid->revision = SD_CID_REV(resp);
out_cid->serial = SD_CID_PSN(resp);
out_cid->date = SD_CID_MDT(resp);
return SDMMC_OK;
}
sdmmc_err_t sdmmc_decode_csd(sdmmc_response_t response, sdmmc_csd_t* out_csd)
{
out_csd->csd_ver = SD_CSD_CSDVER(response);
switch (out_csd->csd_ver) {
case SD_CSD_CSDVER_2_0:
out_csd->capacity = SD_CSD_V2_CAPACITY(response);
out_csd->read_block_len = SD_CSD_V2_BL_LEN;
break;
case SD_CSD_CSDVER_1_0:
out_csd->capacity = SD_CSD_CAPACITY(response);
out_csd->read_block_len = SD_CSD_READ_BL_LEN(response);
break;
default:
ESP_LOGE(TAG, "unknown SD CSD structure version 0x%x", out_csd->csd_ver);
return SDMMC_ERR_NOT_SUPPORTED;
}
out_csd->card_command_class = SD_CSD_CCC(response);
int read_bl_size = 1 << out_csd->read_block_len;
out_csd->sector_size = TSD_MIN(read_bl_size, 512);
if (out_csd->sector_size < read_bl_size) {
out_csd->capacity *= read_bl_size / out_csd->sector_size;
}
int speed = SD_CSD_SPEED(response);
if (speed == SD_CSD_SPEED_50_MHZ) {
out_csd->tr_speed = 50000000;
} else {
out_csd->tr_speed = 25000000;
}
return SDMMC_OK;
}
sdmmc_err_t sdmmc_decode_scr(uint32_t *raw_scr, sdmmc_scr_t* out_scr)
{
sdmmc_response_t resp = { 0 };
resp[1] = __builtin_bswap32(raw_scr[0]);
resp[0] = __builtin_bswap32(raw_scr[1]);
int ver = SCR_STRUCTURE(resp);
if (ver != 0) {
return SDMMC_ERR_NOT_SUPPORTED;
}
out_scr->sd_spec = SCR_SD_SPEC(resp);
out_scr->bus_width = SCR_SD_BUS_WIDTHS(resp);
return SDMMC_OK;
}

View File

@ -0,0 +1,4 @@
idf_component_register(SRC_DIRS "."
PRIV_INCLUDE_DIRS "."
PRIV_REQUIRES cmock sdmmc
)

View File

@ -0,0 +1 @@
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

584
lib/sdmmc/test/test_sd.c Normal file
View File

@ -0,0 +1,584 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include "unity.h"
#include "driver/gpio.h"
#include "soc/soc_caps.h"
#if SOC_SDMMC_HOST_SUPPORTED
#include "driver/sdmmc_host.h"
#endif
#include "driver/sdspi_host.h"
#include "driver/sdmmc_defs.h"
#include "sdmmc_cmd.h"
#include "esp_log.h"
#include "esp_heap_caps.h"
#include "esp_rom_gpio.h"
// Can't test eMMC (slot 0) and PSRAM together
#ifndef CONFIG_SPIRAM
#define WITH_EMMC_TEST
#endif
/* power supply enable pin */
#define SD_TEST_BOARD_VSEL_EN_GPIO 27
/* power supply voltage select pin */
#define SD_TEST_BOARD_VSEL_GPIO 26
#define SD_TEST_BOARD_VSEL_3V3 1
#define SD_TEST_BOARD_VSEL_1V8 0
#define TEST_SDSPI_DMACHAN 1
/* time to wait for reset / power-on */
#define SD_TEST_BOARD_PWR_RST_DELAY_MS 5
#define SD_TEST_BOARD_PWR_ON_DELAY_MS 50
/* gpio which is not connected to actual CD pin, used to simulate CD behavior */
#define CD_WP_TEST_GPIO 18
__attribute__((unused)) static void sd_test_board_power_on(void)
{
gpio_set_direction(SD_TEST_BOARD_VSEL_GPIO, GPIO_MODE_OUTPUT);
gpio_set_level(SD_TEST_BOARD_VSEL_GPIO, SD_TEST_BOARD_VSEL_3V3);
gpio_set_direction(SD_TEST_BOARD_VSEL_EN_GPIO, GPIO_MODE_OUTPUT);
gpio_set_level(SD_TEST_BOARD_VSEL_EN_GPIO, 0);
usleep(SD_TEST_BOARD_PWR_RST_DELAY_MS * 1000);
gpio_set_level(SD_TEST_BOARD_VSEL_EN_GPIO, 1);
usleep(SD_TEST_BOARD_PWR_ON_DELAY_MS * 1000);
}
__attribute__((unused)) static void sd_test_board_power_off(void)
{
gpio_set_level(SD_TEST_BOARD_VSEL_EN_GPIO, 0);
gpio_set_direction(SD_TEST_BOARD_VSEL_GPIO, GPIO_MODE_INPUT);
gpio_set_level(SD_TEST_BOARD_VSEL_GPIO, 0);
gpio_set_direction(SD_TEST_BOARD_VSEL_EN_GPIO, GPIO_MODE_INPUT);
}
TEST_CASE("MMC_RSP_BITS", "[sd]")
{
uint32_t data[2] = { 0x01234567, 0x89abcdef };
TEST_ASSERT_EQUAL_HEX32(0x7, MMC_RSP_BITS(data, 0, 4));
TEST_ASSERT_EQUAL_HEX32(0x567, MMC_RSP_BITS(data, 0, 12));
TEST_ASSERT_EQUAL_HEX32(0xf0, MMC_RSP_BITS(data, 28, 8));
TEST_ASSERT_EQUAL_HEX32(0x3, MMC_RSP_BITS(data, 1, 3));
TEST_ASSERT_EQUAL_HEX32(0x11, MMC_RSP_BITS(data, 59, 5));
}
#if SOC_SDMMC_HOST_SUPPORTED
static void probe_sd(int slot, int width, int freq_khz, int ddr)
{
sd_test_board_power_on();
sdmmc_host_t config = SDMMC_HOST_DEFAULT();
config.slot = slot;
config.max_freq_khz = freq_khz;
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
if (width == 1) {
config.flags = SDMMC_HOST_FLAG_1BIT;
slot_config.width = 1;
} else if (width == 4) {
config.flags &= ~SDMMC_HOST_FLAG_8BIT;
slot_config.width = 4;
} else {
assert(!ddr && "host driver does not support 8-line DDR mode yet");
}
if (!ddr) {
config.flags &= ~SDMMC_HOST_FLAG_DDR;
}
TEST_ESP_OK(sdmmc_host_init());
TEST_ESP_OK(sdmmc_host_init_slot(slot, &slot_config));
sdmmc_card_t* card = malloc(sizeof(sdmmc_card_t));
TEST_ASSERT_NOT_NULL(card);
TEST_ESP_OK(sdmmc_card_init(&config, card));
sdmmc_card_print_info(stdout, card);
uint8_t* buffer = heap_caps_malloc(512, MALLOC_CAP_DMA);
TEST_ESP_OK(sdmmc_read_sectors(card, buffer, 0, 1));
free(buffer);
TEST_ESP_OK(sdmmc_host_deinit());
free(card);
sd_test_board_power_off();
}
TEST_CASE("probe SD, slot 1, 4-bit", "[sd][test_env=UT_T1_SDMODE]")
{
probe_sd(SDMMC_HOST_SLOT_1, 4, SDMMC_FREQ_PROBING, 0);
probe_sd(SDMMC_HOST_SLOT_1, 4, SDMMC_FREQ_DEFAULT, 0);
probe_sd(SDMMC_HOST_SLOT_1, 4, SDMMC_FREQ_HIGHSPEED, 0);
}
TEST_CASE("probe SD, slot 1, 1-bit", "[sd][test_env=UT_T1_SDMODE]")
{
probe_sd(SDMMC_HOST_SLOT_1, 1, SDMMC_FREQ_PROBING, 0);
probe_sd(SDMMC_HOST_SLOT_1, 1, SDMMC_FREQ_DEFAULT, 0);
probe_sd(SDMMC_HOST_SLOT_1, 1, SDMMC_FREQ_HIGHSPEED, 0);
}
#ifdef WITH_EMMC_TEST
TEST_CASE("probe eMMC, slot 0, 4-bit, DDR", "[sd][test_env=EMMC]")
{
probe_sd(SDMMC_HOST_SLOT_0, 4, SDMMC_FREQ_HIGHSPEED, 1);
}
TEST_CASE("probe eMMC, slot 0, 8-bit", "[sd][test_env=EMMC]")
{
probe_sd(SDMMC_HOST_SLOT_0, 8, SDMMC_FREQ_PROBING, 0);
probe_sd(SDMMC_HOST_SLOT_0, 8, SDMMC_FREQ_DEFAULT, 0);
probe_sd(SDMMC_HOST_SLOT_0, 8, SDMMC_FREQ_HIGHSPEED, 0);
}
#endif // WITH_EMMC_TEST
TEST_CASE("probe SD, slot 0, 4-bit", "[sd][test_env=UT_T1_SDCARD][ignore]")
{
probe_sd(SDMMC_HOST_SLOT_0, 4, SDMMC_FREQ_PROBING, 0);
probe_sd(SDMMC_HOST_SLOT_0, 4, SDMMC_FREQ_DEFAULT, 0);
probe_sd(SDMMC_HOST_SLOT_0, 4, SDMMC_FREQ_HIGHSPEED, 0);
}
TEST_CASE("probe SD, slot 0, 1-bit", "[sd][test_env=UT_T1_SDCARD][ignore]")
{
probe_sd(SDMMC_HOST_SLOT_0, 1, SDMMC_FREQ_PROBING, 0);
probe_sd(SDMMC_HOST_SLOT_0, 1, SDMMC_FREQ_DEFAULT, 0);
probe_sd(SDMMC_HOST_SLOT_0, 1, SDMMC_FREQ_HIGHSPEED, 0);
}
#endif
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32C3)
//No runners
static void test_sdspi_init_bus(spi_host_device_t host, int mosi_pin, int miso_pin, int clk_pin, int dma_chan)
{
spi_bus_config_t bus_config = {
.mosi_io_num = mosi_pin,
.miso_io_num = miso_pin,
.sclk_io_num = clk_pin,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
};
esp_err_t err = spi_bus_initialize(host, &bus_config, dma_chan);
TEST_ESP_OK(err);
}
static void test_sdspi_deinit_bus(spi_host_device_t host)
{
esp_err_t err = spi_bus_free(host);
TEST_ESP_OK(err);
}
static void probe_core(int slot)
{
sdmmc_host_t config = SDSPI_HOST_DEFAULT();
config.slot = slot;
sdmmc_card_t* card = malloc(sizeof(sdmmc_card_t));
TEST_ASSERT_NOT_NULL(card);
TEST_ESP_OK(sdmmc_card_init(&config, card));
sdmmc_card_print_info(stdout, card);
free(card);
}
static void probe_spi(int freq_khz, int pin_miso, int pin_mosi, int pin_sck, int pin_cs)
{
sd_test_board_power_on();
sdspi_dev_handle_t handle;
sdspi_device_config_t dev_config = SDSPI_DEVICE_CONFIG_DEFAULT();
dev_config.gpio_cs = pin_cs;
test_sdspi_init_bus(dev_config.host_id, pin_mosi, pin_miso, pin_sck, TEST_SDSPI_DMACHAN);
TEST_ESP_OK(sdspi_host_init());
TEST_ESP_OK(sdspi_host_init_device(&dev_config, &handle));
probe_core(handle);
TEST_ESP_OK(sdspi_host_deinit());
test_sdspi_deinit_bus(dev_config.host_id);
sd_test_board_power_off();
}
static void probe_spi_legacy(int freq_khz, int pin_miso, int pin_mosi, int pin_sck, int pin_cs)
{
sd_test_board_power_on();
sdmmc_host_t config = SDSPI_HOST_DEFAULT();
sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT();
slot_config.gpio_miso = pin_miso;
slot_config.gpio_mosi = pin_mosi;
slot_config.gpio_sck = pin_sck;
slot_config.gpio_cs = pin_cs;
TEST_ESP_OK(sdspi_host_init());
TEST_ESP_OK(sdspi_host_init_slot(config.slot, &slot_config));
probe_core(config.slot);
TEST_ESP_OK(sdspi_host_deinit());
sd_test_board_power_off();
}
TEST_CASE("probe SD in SPI mode, slot 1", "[sd][test_env=UT_T1_SPIMODE]")
{
probe_spi(SDMMC_FREQ_DEFAULT, 2, 15, 14, 13);
probe_spi_legacy(SDMMC_FREQ_DEFAULT, 2, 15, 14, 13);
}
TEST_CASE("probe SD in SPI mode, slot 0", "[sd][test_env=UT_T1_SDCARD][ignore]")
{
probe_spi(SDMMC_FREQ_DEFAULT, 7, 11, 6, 10);
probe_spi_legacy(SDMMC_FREQ_DEFAULT, 7, 11, 6, 10);
}
#endif //DISABLED(ESP32S2)
// Fill buffer pointed to by 'dst' with 'count' 32-bit ints generated
// from 'rand' with the starting value of 'seed'
__attribute__((unused)) static void fill_buffer(uint32_t seed, uint8_t* dst, size_t count) {
srand(seed);
for (size_t i = 0; i < count; ++i) {
uint32_t val = rand();
memcpy(dst + i * sizeof(uint32_t), &val, sizeof(val));
}
}
// Check if the buffer pointed to by 'dst' contains 'count' 32-bit
// ints generated from 'rand' with the starting value of 'seed'
__attribute__((unused)) static void check_buffer(uint32_t seed, const uint8_t* src, size_t count) {
srand(seed);
for (size_t i = 0; i < count; ++i) {
uint32_t val;
memcpy(&val, src + i * sizeof(uint32_t), sizeof(val));
TEST_ASSERT_EQUAL_HEX32(rand(), val);
}
}
__attribute__((unused)) static void do_single_write_read_test(sdmmc_card_t* card,
size_t start_block, size_t block_count, size_t alignment)
{
size_t block_size = card->csd.sector_size;
size_t total_size = block_size * block_count;
printf(" %8d | %3d | %d | %4.1f ", start_block, block_count, alignment, total_size / 1024.0f);
uint32_t* buffer = heap_caps_malloc(total_size + 4, MALLOC_CAP_DMA);
size_t offset = alignment % 4;
uint8_t* c_buffer = (uint8_t*) buffer + offset;
fill_buffer(start_block, c_buffer, total_size / sizeof(buffer[0]));
struct timeval t_start_wr;
gettimeofday(&t_start_wr, NULL);
TEST_ESP_OK(sdmmc_write_sectors(card, c_buffer, start_block, block_count));
struct timeval t_stop_wr;
gettimeofday(&t_stop_wr, NULL);
float time_wr = 1e3f * (t_stop_wr.tv_sec - t_start_wr.tv_sec) + 1e-3f * (t_stop_wr.tv_usec - t_start_wr.tv_usec);
memset(buffer, 0xbb, total_size + 4);
struct timeval t_start_rd;
gettimeofday(&t_start_rd, NULL);
TEST_ESP_OK(sdmmc_read_sectors(card, c_buffer, start_block, block_count));
struct timeval t_stop_rd;
gettimeofday(&t_stop_rd, NULL);
float time_rd = 1e3f * (t_stop_rd.tv_sec - t_start_rd.tv_sec) + 1e-3f * (t_stop_rd.tv_usec - t_start_rd.tv_usec);
printf(" | %6.2f | %5.2f | %6.2f | %5.2f\n",
time_wr, total_size / (time_wr / 1000) / (1024 * 1024),
time_rd, total_size / (time_rd / 1000) / (1024 * 1024));
check_buffer(start_block, c_buffer, total_size / sizeof(buffer[0]));
free(buffer);
}
__attribute__((unused)) static void read_write_test(sdmmc_card_t* card)
{
sdmmc_card_print_info(stdout, card);
printf(" sector | count | align | size(kB) | wr_time(ms) | wr_speed(MB/s) | rd_time(ms) | rd_speed(MB/s)\n");
do_single_write_read_test(card, 0, 1, 4);
do_single_write_read_test(card, 0, 4, 4);
do_single_write_read_test(card, 1, 16, 4);
do_single_write_read_test(card, 16, 32, 4);
do_single_write_read_test(card, 48, 64, 4);
do_single_write_read_test(card, 128, 128, 4);
do_single_write_read_test(card, card->csd.capacity - 64, 32, 4);
do_single_write_read_test(card, card->csd.capacity - 64, 64, 4);
do_single_write_read_test(card, card->csd.capacity - 8, 1, 4);
do_single_write_read_test(card, card->csd.capacity/2, 1, 4);
do_single_write_read_test(card, card->csd.capacity/2, 4, 4);
do_single_write_read_test(card, card->csd.capacity/2, 8, 4);
do_single_write_read_test(card, card->csd.capacity/2, 16, 4);
do_single_write_read_test(card, card->csd.capacity/2, 32, 4);
do_single_write_read_test(card, card->csd.capacity/2, 64, 4);
do_single_write_read_test(card, card->csd.capacity/2, 128, 4);
do_single_write_read_test(card, card->csd.capacity/2, 1, 1);
do_single_write_read_test(card, card->csd.capacity/2, 8, 1);
do_single_write_read_test(card, card->csd.capacity/2, 128, 1);
}
#if SOC_SDMMC_HOST_SUPPORTED
void test_sd_rw_blocks(int slot, int width)
{
sdmmc_host_t config = SDMMC_HOST_DEFAULT();
config.max_freq_khz = SDMMC_FREQ_HIGHSPEED;
config.slot = slot;
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
if (width != 0) {
slot_config.width = width;
}
if (slot_config.width == 8) {
config.flags &= ~SDMMC_HOST_FLAG_DDR;
}
TEST_ESP_OK(sdmmc_host_init());
TEST_ESP_OK(sdmmc_host_init_slot(slot, &slot_config));
sdmmc_card_t* card = malloc(sizeof(sdmmc_card_t));
TEST_ASSERT_NOT_NULL(card);
TEST_ESP_OK(sdmmc_card_init(&config, card));
read_write_test(card);
free(card);
TEST_ESP_OK(sdmmc_host_deinit());
}
TEST_CASE("SDMMC read/write test (SD slot 1)", "[sd][test_env=UT_T1_SDMODE]")
{
sd_test_board_power_on();
test_sd_rw_blocks(1, 4);
sd_test_board_power_off();
}
#ifdef WITH_EMMC_TEST
TEST_CASE("SDMMC read/write test (eMMC slot 0, 4 line DDR)", "[sd][test_env=EMMC]")
{
sd_test_board_power_on();
test_sd_rw_blocks(0, 4);
sd_test_board_power_off();
}
TEST_CASE("SDMMC read/write test (eMMC slot 0, 8 line)", "[sd][test_env=EMMC]")
{
sd_test_board_power_on();
test_sd_rw_blocks(0, 8);
sd_test_board_power_off();
}
#endif // WITH_EMMC_TEST
#endif // SDMMC_HOST_SUPPORTED
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32C3)
//No runners
TEST_CASE("SDMMC read/write test (SD slot 1, in SPI mode)", "[sdspi][test_env=UT_T1_SPIMODE]")
{
sd_test_board_power_on();
sdspi_dev_handle_t handle;
sdspi_device_config_t dev_config = SDSPI_DEVICE_CONFIG_DEFAULT();
test_sdspi_init_bus(dev_config.host_id, GPIO_NUM_15, GPIO_NUM_2, GPIO_NUM_14, TEST_SDSPI_DMACHAN);
TEST_ESP_OK(sdspi_host_init());
TEST_ESP_OK(sdspi_host_init_device(&dev_config, &handle));
sdmmc_host_t config = SDSPI_HOST_DEFAULT();
config.slot = handle;
// This test can only run under 20MHz on ESP32, because the runner connects the card to
// non-IOMUX pins of HSPI.
sdmmc_card_t* card = malloc(sizeof(sdmmc_card_t));
TEST_ASSERT_NOT_NULL(card);
TEST_ESP_OK(sdmmc_card_init(&config, card));
read_write_test(card);
TEST_ESP_OK(sdspi_host_deinit());
free(card);
test_sdspi_deinit_bus(dev_config.host_id);
sd_test_board_power_off();
}
#endif //DISABLED_FOR_TARGETS(ESP32S2, ESP32C3)
#if SOC_SDMMC_HOST_SUPPORTED
TEST_CASE("reads and writes with an unaligned buffer", "[sd][test_env=UT_T1_SDMODE]")
{
sd_test_board_power_on();
sdmmc_host_t config = SDMMC_HOST_DEFAULT();
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
TEST_ESP_OK(sdmmc_host_init());
TEST_ESP_OK(sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config));
sdmmc_card_t* card = malloc(sizeof(sdmmc_card_t));
TEST_ASSERT_NOT_NULL(card);
TEST_ESP_OK(sdmmc_card_init(&config, card));
const size_t buffer_size = 4096;
const size_t block_count = buffer_size / 512;
const size_t extra = 4;
uint8_t* buffer = heap_caps_malloc(buffer_size + extra, MALLOC_CAP_DMA);
// Check read behavior: do aligned write, then unaligned read
const uint32_t seed = 0x89abcdef;
fill_buffer(seed, buffer, buffer_size / sizeof(uint32_t));
TEST_ESP_OK(sdmmc_write_sectors(card, buffer, 0, block_count));
memset(buffer, 0xcc, buffer_size + extra);
TEST_ESP_OK(sdmmc_read_sectors(card, buffer + 1, 0, block_count));
check_buffer(seed, buffer + 1, buffer_size / sizeof(uint32_t));
// Check write behavior: do unaligned write, then aligned read
fill_buffer(seed, buffer + 1, buffer_size / sizeof(uint32_t));
TEST_ESP_OK(sdmmc_write_sectors(card, buffer + 1, 8, block_count));
memset(buffer, 0xcc, buffer_size + extra);
TEST_ESP_OK(sdmmc_read_sectors(card, buffer, 8, block_count));
check_buffer(seed, buffer, buffer_size / sizeof(uint32_t));
free(buffer);
free(card);
TEST_ESP_OK(sdmmc_host_deinit());
sd_test_board_power_off();
}
#endif
__attribute__((unused)) static void test_cd_input(int gpio_cd_num, const sdmmc_host_t* config)
{
sdmmc_card_t* card = malloc(sizeof(sdmmc_card_t));
TEST_ASSERT_NOT_NULL(card);
// SDMMC host should have configured CD as input.
// Enable output as well (not using the driver, to avoid touching input
// enable bits).
esp_rom_gpio_connect_out_signal(gpio_cd_num, SIG_GPIO_OUT_IDX, false, false);
REG_WRITE(GPIO_ENABLE_W1TS_REG, BIT(gpio_cd_num));
// Check that card initialization fails if CD is high
REG_WRITE(GPIO_OUT_W1TS_REG, BIT(gpio_cd_num));
usleep(1000);
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, sdmmc_card_init(config, card));
// Check that card initialization succeeds if CD is low
REG_WRITE(GPIO_OUT_W1TC_REG, BIT(gpio_cd_num));
usleep(1000);
TEST_ESP_OK(sdmmc_card_init(config, card));
free(card);
}
#if SOC_SDMMC_HOST_SUPPORTED
TEST_CASE("CD input works in SD mode", "[sd][test_env=UT_T1_SDMODE]")
{
sd_test_board_power_on();
sdmmc_host_t config = SDMMC_HOST_DEFAULT();
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
slot_config.gpio_cd = CD_WP_TEST_GPIO;
TEST_ESP_OK(sdmmc_host_init());
TEST_ESP_OK(sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config));
test_cd_input(CD_WP_TEST_GPIO, &config);
TEST_ESP_OK(sdmmc_host_deinit());
sd_test_board_power_off();
}
#endif
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32C3)
//No runners
TEST_CASE("CD input works in SPI mode", "[sd][test_env=UT_T1_SPIMODE]")
{
sd_test_board_power_on();
sdspi_dev_handle_t handle;
sdspi_device_config_t dev_config = SDSPI_DEVICE_CONFIG_DEFAULT();
dev_config.gpio_cd = CD_WP_TEST_GPIO;
test_sdspi_init_bus(dev_config.host_id, GPIO_NUM_15, GPIO_NUM_2, GPIO_NUM_14, TEST_SDSPI_DMACHAN);
TEST_ESP_OK(sdspi_host_init());
TEST_ESP_OK(sdspi_host_init_device(&dev_config, &handle));
sdmmc_host_t config = SDSPI_HOST_DEFAULT();
config.slot = handle;
test_cd_input(CD_WP_TEST_GPIO, &config);
TEST_ESP_OK(sdspi_host_deinit());
test_sdspi_deinit_bus(dev_config.host_id);
sd_test_board_power_off();
}
#endif //DISABLED_FOR_TARGETS(ESP32S2)
__attribute__((unused)) static void test_wp_input(int gpio_wp_num, const sdmmc_host_t* config)
{
sdmmc_card_t* card = malloc(sizeof(sdmmc_card_t));
TEST_ASSERT_NOT_NULL(card);
// SDMMC host should have configured WP as input.
// Enable output as well (not using the driver, to avoid touching input
// enable bits).
esp_rom_gpio_connect_out_signal(gpio_wp_num, SIG_GPIO_OUT_IDX, false, false);
REG_WRITE(GPIO_ENABLE_W1TS_REG, BIT(gpio_wp_num));
// Check that the card can be initialized with WP low
REG_WRITE(GPIO_OUT_W1TC_REG, BIT(gpio_wp_num));
TEST_ESP_OK(sdmmc_card_init(config, card));
uint32_t* data = heap_caps_calloc(1, 512, MALLOC_CAP_DMA);
// Check that card write succeeds if WP is high
REG_WRITE(GPIO_OUT_W1TS_REG, BIT(gpio_wp_num));
usleep(1000);
TEST_ESP_OK(sdmmc_write_sectors(card, &data, 0, 1));
// Check that write fails if WP is low
REG_WRITE(GPIO_OUT_W1TC_REG, BIT(gpio_wp_num));
usleep(1000);
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, sdmmc_write_sectors(card, &data, 0, 1));
// ...but reads still work
TEST_ESP_OK(sdmmc_read_sectors(card, &data, 0, 1));
free(data);
free(card);
}
#if SOC_SDMMC_HOST_SUPPORTED
TEST_CASE("WP input works in SD mode", "[sd][test_env=UT_T1_SDMODE]")
{
sd_test_board_power_on();
sdmmc_host_t config = SDMMC_HOST_DEFAULT();
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
slot_config.gpio_wp = CD_WP_TEST_GPIO;
TEST_ESP_OK(sdmmc_host_init());
TEST_ESP_OK(sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config));
test_wp_input(CD_WP_TEST_GPIO, &config);
TEST_ESP_OK(sdmmc_host_deinit());
sd_test_board_power_off();
}
#endif
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32C3)
//No runners
TEST_CASE("WP input works in SPI mode", "[sd][test_env=UT_T1_SPIMODE]")
{
sd_test_board_power_on();
sdspi_dev_handle_t handle;
sdspi_device_config_t dev_config = SDSPI_DEVICE_CONFIG_DEFAULT();
dev_config.gpio_wp = CD_WP_TEST_GPIO;
test_sdspi_init_bus(dev_config.host_id, GPIO_NUM_15, GPIO_NUM_2, GPIO_NUM_14, TEST_SDSPI_DMACHAN);
TEST_ESP_OK(sdspi_host_init());
TEST_ESP_OK(sdspi_host_init_device(&dev_config, &handle));
sdmmc_host_t config = SDSPI_HOST_DEFAULT();
config.slot = handle;
test_wp_input(CD_WP_TEST_GPIO, &config);
TEST_ESP_OK(sdspi_host_deinit());
test_sdspi_deinit_bus(dev_config.host_id);
sd_test_board_power_off();
}
#endif //DISABLED_FOR_TARGETS(ESP32S2)

388
lib/sdmmc/test/test_sdio.c Normal file
View File

@ -0,0 +1,388 @@
// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "soc/soc_caps.h"
#if SOC_SDMMC_HOST_SUPPORTED
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "esp_log.h"
#include "esp_heap_caps.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/sdmmc_host.h"
#include "driver/sdmmc_defs.h"
#include "sdmmc_cmd.h"
#include "unity.h"
/* Second ESP32 board attached as follows:
* Master Slave
* IO18 EN
* IO19 IO0
* IO14 SD_CLK
* IO15 SD_CMD
* IO2 SD_D0
* IO4 SD_D1
* IO12 SD_D2
* IO13 SD_D3
*/
/* TODO: add SDIO slave header files, remove these definitions */
#define DR_REG_SLC_MASK 0xfffffc00
#define SLCCONF1 (DR_REG_SLC_BASE + 0x60)
#define SLC_SLC0_RX_STITCH_EN (BIT(6))
#define SLC_SLC0_TX_STITCH_EN (BIT(5))
#define SLC0TX_LINK (DR_REG_SLC_BASE + 0x40)
#define SLC_SLC0_TXLINK_PARK (BIT(31))
#define SLC_SLC0_TXLINK_RESTART (BIT(30))
#define SLC_SLC0_TXLINK_START (BIT(29))
#define DR_REG_SLCHOST_MASK 0xfffffc00
#define SLCHOST_STATE_W0 (DR_REG_SLCHOST_BASE + 0x64)
#define SLCHOST_CONF_W0 (DR_REG_SLCHOST_BASE + 0x6C)
#define SLCHOST_CONF_W5 (DR_REG_SLCHOST_BASE + 0x80)
#define SLCHOST_WIN_CMD (DR_REG_SLCHOST_BASE + 0x84)
#define SLC_WIN_CMD_READ 0x80
#define SLC_WIN_CMD_WRITE 0xC0
#define SLC_WIN_CMD_S 8
#define SLC_THRESHOLD_ADDR 0x1f800
static const char* TAG = "sdio_test";
static esp_err_t slave_slchost_reg_read(sdmmc_card_t* card, uint32_t addr, uint32_t* out_val)
{
if ((addr & DR_REG_SLCHOST_MASK) != DR_REG_SLCHOST_BASE) {
ESP_LOGW(TAG, "%s: invalid addr 0x%08x\n", __func__, addr);
return ESP_ERR_INVALID_ARG;
}
return sdmmc_io_read_bytes(card, 1, addr & (~DR_REG_SLCHOST_MASK), out_val, sizeof(*out_val));
}
static esp_err_t slave_slchost_reg_write(sdmmc_card_t* card, uint32_t addr, uint32_t val)
{
if ((addr & DR_REG_SLCHOST_MASK) != DR_REG_SLCHOST_BASE) {
ESP_LOGW(TAG, "%s: invalid addr 0x%08x\n", __func__, addr);
return ESP_ERR_INVALID_ARG;
}
return sdmmc_io_write_bytes(card, 1, addr & (~DR_REG_SLCHOST_MASK), &val, sizeof(val));
}
static esp_err_t slave_slc_reg_read(sdmmc_card_t* card, uint32_t addr, uint32_t* val)
{
if ((addr & DR_REG_SLC_MASK) != DR_REG_SLC_BASE) {
ESP_LOGW(TAG, "%s: invalid addr 0x%08x\n", __func__, addr);
return ESP_ERR_INVALID_ARG;
}
uint32_t word = (addr - DR_REG_SLC_BASE) / 4;
if (word > INT8_MAX) {
return ESP_ERR_INVALID_ARG;
}
uint32_t window_command = word | (SLC_WIN_CMD_READ << SLC_WIN_CMD_S);
esp_err_t err = slave_slchost_reg_write(card, SLCHOST_WIN_CMD, window_command);
if (err != ESP_OK) {
return err;
}
return slave_slchost_reg_read(card, SLCHOST_STATE_W0, val);
}
static esp_err_t slave_slc_reg_write(sdmmc_card_t* card, uint32_t addr, uint32_t val)
{
if ((addr & DR_REG_SLC_MASK) != DR_REG_SLC_BASE) {
ESP_LOGW(TAG, "%s: invalid addr 0x%08x\n", __func__, addr);
return ESP_ERR_INVALID_ARG;
}
uint32_t word = (addr - DR_REG_SLC_BASE) / 4;
if (word > INT8_MAX) {
return ESP_ERR_INVALID_ARG;
}
esp_err_t err = slave_slchost_reg_write(card, SLCHOST_CONF_W5, val);
if (err != ESP_OK) {
return err;
}
uint32_t window_command = word | (SLC_WIN_CMD_WRITE << SLC_WIN_CMD_S);
return slave_slchost_reg_write(card, SLCHOST_WIN_CMD, window_command);
}
/** Reset and put slave into download mode */
static void reset_slave(void)
{
const int pin_en = 18;
const int pin_io0 = 19;
gpio_config_t gpio_cfg = {
.pin_bit_mask = BIT64(pin_en) | BIT64(pin_io0),
.mode = GPIO_MODE_OUTPUT_OD,
};
TEST_ESP_OK(gpio_config(&gpio_cfg));
gpio_set_level(pin_en, 0);
gpio_set_level(pin_io0, 0);
vTaskDelay(10 / portTICK_PERIOD_MS);
gpio_set_level(pin_en, 1);
vTaskDelay(10 / portTICK_PERIOD_MS);
gpio_set_level(pin_io0, 1);
}
static void sdio_slave_common_init(sdmmc_card_t* card)
{
uint8_t card_cap;
esp_err_t err = sdmmc_io_read_byte(card, 0, SD_IO_CCCR_CARD_CAP, &card_cap);
TEST_ESP_OK(err);
printf("CAP: 0x%02x\n", card_cap);
uint8_t hs;
err = sdmmc_io_read_byte(card, 0, SD_IO_CCCR_HIGHSPEED, &hs);
TEST_ESP_OK(err);
printf("HS: 0x%02x\n", hs);
#define FUNC1_EN_MASK (BIT(1))
uint8_t ioe;
err = sdmmc_io_read_byte(card, 0, SD_IO_CCCR_FN_ENABLE, &ioe);
TEST_ESP_OK(err);
printf("IOE: 0x%02x\n", ioe);
uint8_t ior = 0;
err = sdmmc_io_read_byte(card, 0, SD_IO_CCCR_FN_READY, &ior);
TEST_ESP_OK(err);
printf("IOR: 0x%02x\n", ior);
// enable function 1
ioe |= FUNC1_EN_MASK;
err = sdmmc_io_write_byte(card, 0, SD_IO_CCCR_FN_ENABLE, ioe, NULL);
TEST_ESP_OK(err);
err = sdmmc_io_read_byte(card, 0, SD_IO_CCCR_FN_ENABLE, &ioe);
TEST_ESP_OK(err);
printf("IOE: 0x%02x\n", ioe);
// wait for the card to become ready
while ( (ior & FUNC1_EN_MASK) == 0 ) {
err = sdmmc_io_read_byte(card, 0, SD_IO_CCCR_FN_READY, &ior);
TEST_ESP_OK(err);
printf("IOR: 0x%02x\n", ior);
}
// get interrupt status
uint8_t ie;
err = sdmmc_io_read_byte(card, 0, SD_IO_CCCR_INT_ENABLE, &ie);
TEST_ESP_OK(err);
printf("IE: 0x%02x\n", ie);
// enable interrupts for function 1&2 and master enable
ie |= BIT(0) | FUNC1_EN_MASK;
err = sdmmc_io_write_byte(card, 0, SD_IO_CCCR_INT_ENABLE, ie, NULL);
TEST_ESP_OK(err);
err = sdmmc_io_read_byte(card, 0, SD_IO_CCCR_INT_ENABLE, &ie);
TEST_ESP_OK(err);
printf("IE: 0x%02x\n", ie);
}
/** Common for all SDIO devices, set block size for specific function */
static void sdio_slave_set_blocksize(sdmmc_card_t* card, int function, uint16_t bs)
{
const uint8_t* bs_u8 = (const uint8_t*) &bs;
uint16_t bs_read = 0;
uint8_t* bs_read_u8 = (uint8_t*) &bs_read;
uint32_t offset = SD_IO_FBR_START * function;
TEST_ESP_OK( sdmmc_io_write_byte(card, 0, offset + SD_IO_CCCR_BLKSIZEL, bs_u8[0], NULL));
TEST_ESP_OK( sdmmc_io_write_byte(card, 0, offset + SD_IO_CCCR_BLKSIZEH, bs_u8[1], NULL));
TEST_ESP_OK( sdmmc_io_read_byte(card, 0, offset + SD_IO_CCCR_BLKSIZEL, &bs_read_u8[0]));
TEST_ESP_OK( sdmmc_io_read_byte(card, 0, offset + SD_IO_CCCR_BLKSIZEH, &bs_read_u8[1]));
TEST_ASSERT_EQUAL_HEX16(bs, bs_read);
}
/**
* ESP32 ROM code does not set some SDIO slave registers to the defaults
* we need, this function clears/sets some bits.
*/
static void esp32_slave_init_extra(sdmmc_card_t* card)
{
printf("Initialize some ESP32 SDIO slave registers\n");
uint32_t reg_val;
TEST_ESP_OK( slave_slc_reg_read(card, SLCCONF1, &reg_val) );
reg_val &= ~(SLC_SLC0_RX_STITCH_EN | SLC_SLC0_TX_STITCH_EN);
TEST_ESP_OK( slave_slc_reg_write(card, SLCCONF1, reg_val) );
TEST_ESP_OK( slave_slc_reg_read(card, SLC0TX_LINK, &reg_val) );
reg_val |= SLC_SLC0_TXLINK_START;
TEST_ESP_OK( slave_slc_reg_write(card, SLC0TX_LINK, reg_val) );
}
/**
* ESP32 bootloader implements "SIP" protocol which can be used to exchange
* some commands, events, and data packets between the host and the slave.
* This function sends a SIP command, testing CMD53 block writes along the way.
*/
static void esp32_send_sip_command(sdmmc_card_t* card)
{
printf("Test block write using CMD53\n");
const size_t block_size = 512;
uint8_t* data = heap_caps_calloc(1, block_size, MALLOC_CAP_DMA);
struct sip_cmd_bootup {
uint32_t boot_addr;
uint32_t discard_link;
};
struct sip_cmd_write_reg {
uint32_t addr;
uint32_t val;
};
struct sip_hdr {
uint8_t fc[2];
uint16_t len;
uint32_t cmdid;
uint32_t seq;
};
struct sip_hdr* hdr = (struct sip_hdr*) data;
size_t len;
#define SEND_WRITE_REG_CMD
#ifdef SEND_WRITE_REG_CMD
struct sip_cmd_write_reg *write_reg = (struct sip_cmd_write_reg*) (data + sizeof(*hdr));
len = sizeof(*hdr) + sizeof(*write_reg);
hdr->cmdid = 3; /* SIP_CMD_WRITE_REG */
write_reg->addr = GPIO_ENABLE_W1TS_REG;
write_reg->val = BIT(0) | BIT(2) | BIT(4); /* Turn of RGB LEDs on WROVER-KIT */
#else
struct sip_cmd_bootup *bootup = (struct sip_cmd_bootup*) (data + sizeof(*hdr));
len = sizeof(*hdr) + sizeof(*bootup);
hdr->cmdid = 5; /* SIP_CMD_BOOTUP */
bootup->boot_addr = 0x4005a980; /* start_tb_console function in ROM */
bootup->discard_link = 1;
#endif
hdr->len = len;
TEST_ESP_OK( sdmmc_io_write_blocks(card, 1, SLC_THRESHOLD_ADDR - len, data, block_size) );
free(data);
}
static void test_cmd52_read_write_single_byte(sdmmc_card_t* card)
{
esp_err_t err;
printf("Write bytes to slave's W0_REG using CMD52\n");
const size_t scratch_area_reg = SLCHOST_CONF_W0 - DR_REG_SLCHOST_BASE;
const uint8_t test_byte_1 = 0xa5;
const uint8_t test_byte_2 = 0xb6;
// used to check Read-After-Write
uint8_t test_byte_1_raw;
uint8_t test_byte_2_raw;
uint8_t val = 0;
err = sdmmc_io_write_byte(card, 1, scratch_area_reg, test_byte_1, &test_byte_1_raw);
TEST_ESP_OK(err);
TEST_ASSERT_EQUAL_UINT8(test_byte_1, test_byte_1_raw);
err = sdmmc_io_write_byte(card, 1, scratch_area_reg + 1, test_byte_2, &test_byte_2_raw);
TEST_ESP_OK(err);
TEST_ASSERT_EQUAL_UINT8(test_byte_2, test_byte_2_raw);
printf("Read back bytes using CMD52\n");
TEST_ESP_OK(sdmmc_io_read_byte(card, 1, scratch_area_reg, &val));
TEST_ASSERT_EQUAL_UINT8(test_byte_1, val);
TEST_ESP_OK(sdmmc_io_read_byte(card, 1, scratch_area_reg + 1, &val));
TEST_ASSERT_EQUAL_UINT8(test_byte_2, val);
}
static void test_cmd53_read_write_multiple_bytes(sdmmc_card_t* card, size_t n_bytes)
{
printf("Write multiple bytes using CMD53\n");
const size_t scratch_area_reg = SLCHOST_CONF_W0 - DR_REG_SLCHOST_BASE;
uint8_t* src = heap_caps_malloc(512, MALLOC_CAP_DMA);
uint32_t* src_32 = (uint32_t*) src;
for (size_t i = 0; i < (n_bytes + 3) / 4; ++i) {
src_32[i] = rand();
}
TEST_ESP_OK(sdmmc_io_write_bytes(card, 1, scratch_area_reg, src, n_bytes));
ESP_LOG_BUFFER_HEX(TAG, src, n_bytes);
printf("Read back using CMD52\n");
uint8_t* dst = heap_caps_malloc(512, MALLOC_CAP_DMA);
for (size_t i = 0; i < n_bytes; ++i) {
TEST_ESP_OK(sdmmc_io_read_byte(card, 1, scratch_area_reg + i, &dst[i]));
}
ESP_LOG_BUFFER_HEX(TAG, dst, n_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(src, dst, n_bytes);
printf("Read back using CMD53\n");
TEST_ESP_OK(sdmmc_io_read_bytes(card, 1, scratch_area_reg, dst, n_bytes));
ESP_LOG_BUFFER_HEX(TAG, dst, n_bytes);
TEST_ASSERT_EQUAL_UINT8_ARRAY(src, dst, n_bytes);
free(src);
free(dst);
}
TEST_CASE("can probe and talk to ESP32 SDIO slave", "[sdio][ignore]")
{
reset_slave();
/* Probe */
sdmmc_host_t config = SDMMC_HOST_DEFAULT();
config.flags = SDMMC_HOST_FLAG_1BIT;
config.max_freq_khz = SDMMC_FREQ_PROBING;
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
(sdmmc_host_init());
(sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config));
sdmmc_card_t* card = malloc(sizeof(sdmmc_card_t));
TEST_ASSERT_NOT_NULL(card);
TEST_ESP_OK(sdmmc_card_init(&config, card));
sdmmc_card_print_info(stdout, card);
/* Set up standard SDIO registers */
sdio_slave_common_init(card);
srand(0);
for (int repeat = 0; repeat < 4; ++repeat) {
test_cmd52_read_write_single_byte(card);
test_cmd53_read_write_multiple_bytes(card, 1);
test_cmd53_read_write_multiple_bytes(card, 2);
test_cmd53_read_write_multiple_bytes(card, 3);
test_cmd53_read_write_multiple_bytes(card, 4);
test_cmd53_read_write_multiple_bytes(card, 5);
test_cmd53_read_write_multiple_bytes(card, 23);
test_cmd53_read_write_multiple_bytes(card, 24);
}
sdio_slave_set_blocksize(card, 0, 512);
sdio_slave_set_blocksize(card, 1, 512);
esp32_slave_init_extra(card);
esp32_send_sip_command(card);
TEST_ESP_OK(sdmmc_host_deinit());
free(card);
}
#endif //SOC_SDMMC_HOST_SUPPORTED

@ -1 +1 @@
Subproject commit 43aac7074be0d14e72cb04eaddcddf1a926c6a74
Subproject commit ae73873b5cba0eb11c89165f4559964940430d44

View File

@ -584,6 +584,7 @@ msgstr "Kedua pin harus mendukung hardware interrut"
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr "Kecerahan harus di antara 0-1.0"
@ -1242,6 +1243,10 @@ msgstr "Otentikasi tidak cukup"
msgid "Insufficient encryption"
msgstr "Enkripsi tidak cukup"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr ""
@ -1478,6 +1483,10 @@ msgstr "Panjang kata/bit tidak valid"
msgid "Key must be 16, 24, or 32 bytes long"
msgstr "Panjang kunci harus 16, 24, atau 32 byte"
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr ""
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr "LHS dari keyword arg harus menjadi sebuah id"
@ -2116,6 +2125,10 @@ msgstr "Tingkat sampel harus positif"
msgid "Sample rate too high. It must be less than %d"
msgstr "Nilai sampel terlalu tinggi. Nilai harus kurang dari %d"
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr ""
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr "Pindai sudah dalam proses. Hentikan dengan stop_scan."
@ -2177,10 +2190,6 @@ msgstr "Memisahkan dengan menggunakan sub-captures"
msgid "Stack size must be at least 256"
msgstr "Ukuran stack minimal harus 256"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr ""
@ -2377,7 +2386,7 @@ msgstr "Tidak dapat mengalokasikan buffer untuk signed conversion"
msgid "Unable to create lock"
msgstr ""
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr "Tidak dapat menemukan Tampilan I2C di %x"
@ -3979,12 +3988,14 @@ msgstr ""
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -3999,6 +4010,7 @@ msgstr ""
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4491,6 +4503,7 @@ msgstr ""
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr ""

View File

@ -574,6 +574,7 @@ msgstr ""
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr ""
@ -1221,6 +1222,10 @@ msgstr ""
msgid "Insufficient encryption"
msgstr ""
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr ""
@ -1457,6 +1462,10 @@ msgstr ""
msgid "Key must be 16, 24, or 32 bytes long"
msgstr ""
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr ""
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr ""
@ -2081,6 +2090,10 @@ msgstr ""
msgid "Sample rate too high. It must be less than %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr ""
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr ""
@ -2142,10 +2155,6 @@ msgstr ""
msgid "Stack size must be at least 256"
msgstr ""
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr ""
@ -2342,7 +2351,7 @@ msgstr ""
msgid "Unable to create lock"
msgstr ""
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr ""
@ -3941,12 +3950,14 @@ msgstr ""
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -3961,6 +3972,7 @@ msgstr ""
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4453,6 +4465,7 @@ msgstr ""
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr ""

View File

@ -577,6 +577,7 @@ msgstr ""
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr ""
@ -1224,6 +1225,10 @@ msgstr ""
msgid "Insufficient encryption"
msgstr ""
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr ""
@ -1460,6 +1465,10 @@ msgstr ""
msgid "Key must be 16, 24, or 32 bytes long"
msgstr ""
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr ""
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr ""
@ -2084,6 +2093,10 @@ msgstr ""
msgid "Sample rate too high. It must be less than %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr ""
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr ""
@ -2145,10 +2158,6 @@ msgstr ""
msgid "Stack size must be at least 256"
msgstr ""
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr ""
@ -2345,7 +2354,7 @@ msgstr ""
msgid "Unable to create lock"
msgstr ""
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr ""
@ -3944,12 +3953,14 @@ msgstr ""
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -3964,6 +3975,7 @@ msgstr ""
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4456,6 +4468,7 @@ msgstr ""
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr ""

View File

@ -585,6 +585,7 @@ msgstr "Beide pins müssen Hardware Interrupts unterstützen"
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr "Die Helligkeit muss zwischen 0 und 1.0 liegen"
@ -1241,6 +1242,10 @@ msgstr "Unzureichende Authentifizierung"
msgid "Insufficient encryption"
msgstr "Unzureichende Verschlüsselung"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr ""
@ -1477,6 +1482,10 @@ msgstr "Ungültige Wort- / Bitlänge"
msgid "Key must be 16, 24, or 32 bytes long"
msgstr "Der Schlüssel muss 16, 24 oder 32 Byte lang sein"
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr ""
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr "LHS des Schlüsselwortarguments muss eine id sein"
@ -2113,6 +2122,10 @@ msgstr "Abtastrate muss positiv sein"
msgid "Sample rate too high. It must be less than %d"
msgstr "Abtastrate zu hoch. Wert muss unter %d liegen"
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr ""
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr "Scannen Sie bereits in Bearbeitung. Stoppen Sie mit stop_scan."
@ -2174,10 +2187,6 @@ msgstr "Splitting mit sub-captures"
msgid "Stack size must be at least 256"
msgstr "Die Stackgröße sollte mindestens 256 sein"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr ""
@ -2377,7 +2386,7 @@ msgstr "Konnte keine Buffer für Vorzeichenumwandlung allozieren"
msgid "Unable to create lock"
msgstr ""
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr "Konnte kein I2C Display finden an %x"
@ -4007,12 +4016,14 @@ msgstr "pow() mit 3 Argumenten erfordert Integer"
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -4027,6 +4038,7 @@ msgstr "pow() mit 3 Argumenten erfordert Integer"
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4524,6 +4536,7 @@ msgstr "watchdog Zeitlimit muss größer als 0 sein"
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr "breite muss zwischen (inklusive) 2 und 8 liegen, nicht %d"
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr "breite muss größer als 0 sein"

View File

@ -574,6 +574,7 @@ msgstr ""
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr ""
@ -1221,6 +1222,10 @@ msgstr ""
msgid "Insufficient encryption"
msgstr ""
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr ""
@ -1457,6 +1462,10 @@ msgstr ""
msgid "Key must be 16, 24, or 32 bytes long"
msgstr ""
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr ""
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr ""
@ -2081,6 +2090,10 @@ msgstr ""
msgid "Sample rate too high. It must be less than %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr ""
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr ""
@ -2142,10 +2155,6 @@ msgstr ""
msgid "Stack size must be at least 256"
msgstr ""
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr ""
@ -2342,7 +2351,7 @@ msgstr ""
msgid "Unable to create lock"
msgstr ""
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr ""
@ -3941,12 +3950,14 @@ msgstr ""
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -3961,6 +3972,7 @@ msgstr ""
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4453,6 +4465,7 @@ msgstr ""
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr ""

View File

@ -585,6 +585,7 @@ msgstr "Both pins must support hardware interrupts"
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr "Brightness must be 0-1.0"
@ -1236,6 +1237,10 @@ msgstr "Insufficient authentication"
msgid "Insufficient encryption"
msgstr "Insufficient encryption"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr "Internal audio buffer too small"
@ -1472,6 +1477,10 @@ msgstr "Invalid word/bit length"
msgid "Key must be 16, 24, or 32 bytes long"
msgstr "Key must be 16, 24, or 32 bytes long"
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr ""
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr "LHS of keyword arg must be an id"
@ -2105,6 +2114,10 @@ msgstr "Sample rate must be positive"
msgid "Sample rate too high. It must be less than %d"
msgstr "Sample rate too high. It must be less than %d"
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr ""
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr "Scan already in progess. Stop with stop_scan."
@ -2166,10 +2179,6 @@ msgstr "Splitting with sub-captures"
msgid "Stack size must be at least 256"
msgstr "Stack size must be at least 256"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr "Stereo left must be on PWM channel A"
@ -2373,7 +2382,7 @@ msgstr "Unable to allocate buffers for signed conversion"
msgid "Unable to create lock"
msgstr "Unable to create lock"
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr "Unable to find I2C display at %x"
@ -3978,12 +3987,14 @@ msgstr "pow() with 3 arguments requires integers"
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -3998,6 +4009,7 @@ msgstr "pow() with 3 arguments requires integers"
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4492,6 +4504,7 @@ msgstr "WatchDog timeout must be greater than 0"
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr "width must be from 2 to 8 (inclusive), not %d"
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr "width must be greater than zero"

View File

@ -589,6 +589,7 @@ msgstr "Ambos pines deben soportar interrupciones por hardware"
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr "El brillo debe ser 0-1.0"
@ -1254,6 +1255,10 @@ msgstr "Autenticación insuficiente"
msgid "Insufficient encryption"
msgstr "Cifrado insuficiente"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr ""
@ -1490,6 +1495,10 @@ msgstr "Tamaño no válido de palabra/bit"
msgid "Key must be 16, 24, or 32 bytes long"
msgstr "La llave debe tener 16, 24 o 32 bytes de longitud"
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr ""
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr "LHS del agumento por palabra clave deberia ser un identificador"
@ -2133,6 +2142,10 @@ msgstr "Sample rate debe ser positivo"
msgid "Sample rate too high. It must be less than %d"
msgstr "Frecuencia de muestreo demasiado alta. Debe ser menor a %d"
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr ""
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr "Escaneo en progreso. Usa stop_scan para detener."
@ -2194,10 +2207,6 @@ msgstr "Dividiendo con sub-capturas"
msgid "Stack size must be at least 256"
msgstr "El tamaño de la pila debe ser de al menos 256"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr "Estéreo izquierdo debe estar en el canal PWM A"
@ -2404,7 +2413,7 @@ msgstr "No se pudieron asignar buffers para la conversión con signo"
msgid "Unable to create lock"
msgstr "No se puede crear bloqueo"
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr "No se puede encontrar la pantalla I2C en %x"
@ -4024,12 +4033,14 @@ msgstr "pow() con 3 argumentos requiere enteros"
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -4044,6 +4055,7 @@ msgstr "pow() con 3 argumentos requiere enteros"
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4539,6 +4551,7 @@ msgstr "el tiempo de espera del perro guardián debe ser mayor a 0"
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr "ancho debe estar entre 2 y 8 (inclusivamente), no %d"
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr "el ancho debe ser mayor que cero"

View File

@ -581,6 +581,7 @@ msgstr "Ang parehong mga pin ay dapat na sumusuporta sa hardware interrupts"
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr ""
@ -1236,6 +1237,10 @@ msgstr ""
msgid "Insufficient encryption"
msgstr ""
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr ""
@ -1472,6 +1477,10 @@ msgstr ""
msgid "Key must be 16, 24, or 32 bytes long"
msgstr ""
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr ""
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr "LHS ng keyword arg ay dapat na id"
@ -2101,6 +2110,10 @@ msgstr "Sample rate ay dapat positibo"
msgid "Sample rate too high. It must be less than %d"
msgstr "Sample rate ay masyadong mataas. Ito ay dapat hindi hiigit sa %d"
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr ""
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr ""
@ -2162,10 +2175,6 @@ msgstr "Binibiyak gamit ang sub-captures"
msgid "Stack size must be at least 256"
msgstr "Ang laki ng stack ay dapat na hindi bababa sa 256"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr ""
@ -2362,7 +2371,7 @@ msgstr "Hindi ma-allocate ang buffers para sa naka-sign na conversion"
msgid "Unable to create lock"
msgstr ""
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr ""
@ -3982,12 +3991,14 @@ msgstr "pow() na may 3 argumento kailangan ng integers"
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -4002,6 +4013,7 @@ msgstr "pow() na may 3 argumento kailangan ng integers"
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4498,6 +4510,7 @@ msgstr ""
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr ""

View File

@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: 0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-04 12:55-0600\n"
"PO-Revision-Date: 2021-11-15 18:21+0000\n"
"PO-Revision-Date: 2021-11-26 13:46+0000\n"
"Last-Translator: Maxime Leroy <lisacintosh@gmail.com>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 4.9.1-dev\n"
"X-Generator: Weblate 4.10-dev\n"
#: main.c
msgid ""
@ -591,6 +591,7 @@ msgstr "Les deux broches doivent supporter les interruptions matérielles"
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr "La luminosité doit être de 0 à 1.0"
@ -1267,6 +1268,10 @@ msgstr "Authentification insuffisante"
msgid "Insufficient encryption"
msgstr "Chiffrement insuffisant"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr "L'interface doit être lancée"
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr "Le tampon interne pour l'audio est trop petit"
@ -1328,7 +1333,7 @@ msgstr "Broche DAC non valide fournie"
#: shared-bindings/wifi/Radio.c
msgid "Invalid MAC address"
msgstr ""
msgstr "Adresse MAC invalide"
#: shared-bindings/synthio/__init__.c
msgid "Invalid MIDI file"
@ -1405,7 +1410,7 @@ msgstr "Accès à la mémoire invalide."
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Invalid multicast MAC address"
msgstr ""
msgstr "Adresse MAC multicast invalide"
#: shared-bindings/bitbangio/SPI.c shared-bindings/busio/SPI.c
msgid "Invalid number of bits"
@ -1503,6 +1508,10 @@ msgstr "Longueur de mot / bit invalide"
msgid "Key must be 16, 24, or 32 bytes long"
msgstr "La clé doit comporter 16, 24 ou 32 octets"
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr "La disposition des LED doit correspondre à la taille de l'écran"
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr "La partie gauche de l'argument nommé doit être un identifiant"
@ -1584,7 +1593,7 @@ msgstr "jmp_pin manquant. L'instruction %d va passer à la broche"
#: shared-module/usb_hid/Device.c
#, c-format
msgid "More than %d report ids not supported"
msgstr ""
msgstr "Plus de %d identifiants de rapport ne sont pas supportés"
#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c
msgid "Must be a %q subclass."
@ -1811,11 +1820,11 @@ msgstr ""
#: shared-bindings/_bleio/Adapter.c
msgid "Only connectable advertisements can be directed"
msgstr ""
msgstr "Seuls les avertissements connectables peuvent être dirigés"
#: ports/stm/common-hal/alarm/pin/PinAlarm.c
msgid "Only edge detection is available on this hardware"
msgstr ""
msgstr "Seule la détection des bords est disponible sur ce matériel"
#: shared-bindings/ipaddress/__init__.c
msgid "Only int or string supported for ip"
@ -2145,6 +2154,10 @@ msgstr "Le taux d'échantillonage doit être positif"
msgid "Sample rate too high. It must be less than %d"
msgstr "Taux d'échantillonage trop élevé. Doit être inférieur à %d"
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr "La dimension d'échelle doit être un multiple de 3"
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr "Scan déjà en cours. Arrêtez avec stop_scan."
@ -2206,10 +2219,6 @@ msgstr "Fractionnement avec des sous-captures"
msgid "Stack size must be at least 256"
msgstr "La pile doit être au moins de 256"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr "Canal stéréo gauche doit être sur le canal PWM A"
@ -2264,6 +2273,10 @@ msgid ""
"enough power for the whole circuit and press reset (after ejecting "
"CIRCUITPY)."
msgstr ""
"L'alimentation du microcontrôleur a diminué. Veillez à ce que votre "
"alimentation fournisse\n"
"assez de puissance pour tout le circuit, puis appuyez sur 'reset' (après "
"avoir éjecté CIRCUITPY)."
#: shared-module/audiomixer/MixerVoice.c
msgid "The sample's bits_per_sample does not match the mixer's"
@ -2344,7 +2357,7 @@ msgstr "Quantité de données à écrire est plus que %q"
#: ports/raspberrypi/common-hal/alarm/touch/TouchAlarm.c
#: ports/stm/common-hal/alarm/touch/TouchAlarm.c
msgid "Touch alarms not available"
msgstr ""
msgstr "Les touches d'alarme ne sont pas disponibles"
#: py/obj.c
msgid "Traceback (most recent call last):\n"
@ -2416,7 +2429,7 @@ msgstr "Impossible d'allouer des tampons pour une conversion signée"
msgid "Unable to create lock"
msgstr "Impossible de créer un verrou ('lock')"
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr "Impossible de trouver l'affichage I2C à %x"
@ -2643,7 +2656,7 @@ msgstr "l'argument est une séquence vide"
#: py/objobject.c
msgid "arg must be user-type"
msgstr ""
msgstr "L'argument doit être du type utilisateur"
#: extmod/ulab/code/numpy/numerical.c
msgid "argsort argument must be an ndarray"
@ -2709,7 +2722,7 @@ msgstr "axis trop long"
#: shared-bindings/bitmaptools/__init__.c
msgid "background value out of range of target"
msgstr ""
msgstr "La valeur du fond est hors de portée de la cible"
#: py/builtinevex.c
msgid "bad compile mode"
@ -2824,7 +2837,7 @@ msgstr "ne peut pas assigner à une expression"
#: extmod/moduasyncio.c
msgid "can't cancel self"
msgstr ""
msgstr "ne peut pas s'annuler soi-même"
#: py/obj.c py/objint.c shared-bindings/i2cperipheral/I2CPeripheral.c
#: shared-module/adafruit_pixelbuf/PixelBuf.c
@ -3553,8 +3566,9 @@ msgid "invalid syntax for number"
msgstr "syntaxe invalide pour un nombre"
#: py/objexcept.c
#, fuzzy
msgid "invalid traceback"
msgstr ""
msgstr "traceback invalide"
#: py/objtype.c
msgid "issubclass() arg 1 must be a class"
@ -3791,7 +3805,7 @@ msgstr "pas de tel attribut"
#: shared-bindings/usb_hid/__init__.c
msgid "non-Device in %q"
msgstr ""
msgstr "aucun appareil dans %q"
#: ports/nrf/common-hal/_bleio/Connection.c
msgid "non-UUID found in service_uuids_whitelist"
@ -3850,7 +3864,7 @@ msgstr "l'objet '%s' n'est pas un tuple ou une liste"
#: py/obj.c
msgid "object doesn't support item assignment"
msgstr ""
msgstr "les objets ne supportent pas l'assignation des éléments"
#: py/obj.c
msgid "object doesn't support item deletion"
@ -3862,7 +3876,7 @@ msgstr "l'objet n'a pas de 'len'"
#: py/obj.c
msgid "object isn't subscriptable"
msgstr ""
msgstr "l'objet n'est pas indexable"
#: py/runtime.c
msgid "object not an iterator"
@ -4051,12 +4065,14 @@ msgstr "pow() avec 3 arguments nécessite des entiers"
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -4071,6 +4087,7 @@ msgstr "pow() avec 3 arguments nécessite des entiers"
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4268,7 +4285,7 @@ msgstr "source_bitmap doit avoir une value_count de 8"
#: shared-bindings/wifi/Radio.c
msgid "ssid can't be more than 32 bytes"
msgstr ""
msgstr "un ssid ne peut pas faire plus de 32 octets"
#: py/objstr.c
msgid "start/end indices"
@ -4566,6 +4583,7 @@ msgstr "watchdog timeout doit être supérieur à 0"
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr "width doit être entre 2 et 8 (inclusivement), non %d"
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr "width doit être plus que zero"

View File

@ -574,6 +574,7 @@ msgstr ""
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr ""
@ -1221,6 +1222,10 @@ msgstr ""
msgid "Insufficient encryption"
msgstr ""
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr ""
@ -1457,6 +1462,10 @@ msgstr ""
msgid "Key must be 16, 24, or 32 bytes long"
msgstr ""
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr ""
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr ""
@ -2081,6 +2090,10 @@ msgstr ""
msgid "Sample rate too high. It must be less than %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr ""
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr ""
@ -2142,10 +2155,6 @@ msgstr ""
msgid "Stack size must be at least 256"
msgstr ""
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr ""
@ -2342,7 +2351,7 @@ msgstr ""
msgid "Unable to create lock"
msgstr ""
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr ""
@ -3941,12 +3950,14 @@ msgstr ""
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -3961,6 +3972,7 @@ msgstr ""
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4453,6 +4465,7 @@ msgstr ""
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr ""

View File

@ -589,6 +589,7 @@ msgstr "Entrambi i pin devono supportare gli interrupt hardware"
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr "La luminosità deve essere tra 0-1.0"
@ -1243,6 +1244,10 @@ msgstr ""
msgid "Insufficient encryption"
msgstr ""
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr ""
@ -1482,6 +1487,10 @@ msgstr ""
msgid "Key must be 16, 24, or 32 bytes long"
msgstr ""
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr ""
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr ""
@ -2120,6 +2129,10 @@ msgid "Sample rate too high. It must be less than %d"
msgstr ""
"Frequenza di campionamento troppo alta. Il valore deve essere inferiore a %d"
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr ""
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr ""
@ -2181,10 +2194,6 @@ msgstr "Suddivisione con sotto-catture"
msgid "Stack size must be at least 256"
msgstr "La dimensione dello stack deve essere almeno 256"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr ""
@ -2381,7 +2390,7 @@ msgstr "Ipossibilitato ad allocare buffer per la conversione con segno"
msgid "Unable to create lock"
msgstr ""
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr ""
@ -4004,12 +4013,14 @@ msgstr "pow() con 3 argomenti richiede interi"
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -4024,6 +4035,7 @@ msgstr "pow() con 3 argomenti richiede interi"
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4520,6 +4532,7 @@ msgstr ""
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr ""

View File

@ -581,6 +581,7 @@ msgstr "両方のピンにハードウェア割り込み対応が必要"
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr "brightnessは0から1.0まででなければなりません"
@ -1232,6 +1233,10 @@ msgstr "認証が不十分"
msgid "Insufficient encryption"
msgstr "暗号化が不十分"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr ""
@ -1468,6 +1473,10 @@ msgstr "不正なワード/ビット長"
msgid "Key must be 16, 24, or 32 bytes long"
msgstr "Keyの長さは、16, 24, 32バイトのいずれかでなければなりません"
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr ""
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr "キーワード引数の左辺には識別子が必要"
@ -2095,6 +2104,10 @@ msgstr "サンプルレートは正数でなければなりません"
msgid "Sample rate too high. It must be less than %d"
msgstr "サンプルレートは%d以下でなければなりません"
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr ""
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr "既にスキャン進行中。stop_scanで停止してください"
@ -2156,10 +2169,6 @@ msgstr ""
msgid "Stack size must be at least 256"
msgstr "スタックサイズは少なくとも256以上でなければなりません"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr ""
@ -2357,7 +2366,7 @@ msgstr ""
msgid "Unable to create lock"
msgstr ""
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr "I2Cディスプレイを %x に見つけられません"
@ -3963,12 +3972,14 @@ msgstr "pow()の第3引数には整数が必要"
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -3983,6 +3994,7 @@ msgstr "pow()の第3引数には整数が必要"
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4476,6 +4488,7 @@ msgstr "watchdogのtimeoutは0以上でなければなりません"
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr ""

View File

@ -577,6 +577,7 @@ msgstr ""
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr ""
@ -1224,6 +1225,10 @@ msgstr ""
msgid "Insufficient encryption"
msgstr ""
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr ""
@ -1460,6 +1465,10 @@ msgstr ""
msgid "Key must be 16, 24, or 32 bytes long"
msgstr ""
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr ""
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr ""
@ -2084,6 +2093,10 @@ msgstr ""
msgid "Sample rate too high. It must be less than %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr ""
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr ""
@ -2145,10 +2158,6 @@ msgstr ""
msgid "Stack size must be at least 256"
msgstr ""
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr ""
@ -2346,7 +2355,7 @@ msgstr ""
msgid "Unable to create lock"
msgstr ""
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr ""
@ -3945,12 +3954,14 @@ msgstr ""
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -3965,6 +3976,7 @@ msgstr ""
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4457,6 +4469,7 @@ msgstr ""
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr ""

View File

@ -579,6 +579,7 @@ msgstr "Beide pinnen moeten hardware interrupts ondersteunen"
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr "Helderheid moet tussen de 0 en 1.0 liggen"
@ -1233,6 +1234,10 @@ msgstr "Onvoldoende authenticatie"
msgid "Insufficient encryption"
msgstr "Onvoldoende encryptie"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr ""
@ -1469,6 +1474,10 @@ msgstr "Ongeldig woord/bit lengte"
msgid "Key must be 16, 24, or 32 bytes long"
msgstr "Sleutel moet 16, 24, of 32 bytes lang zijn"
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr ""
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr "LHS van sleutelwoord arg moet een id zijn"
@ -2107,6 +2116,10 @@ msgstr "Sample rate moet positief zijn"
msgid "Sample rate too high. It must be less than %d"
msgstr "Sample rate is te hoog. Moet minder dan %d zijn"
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr ""
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr "Scan wordt al uitvoerd. Stop met stop_scan."
@ -2168,10 +2181,6 @@ msgstr "Splitting met sub-captures"
msgid "Stack size must be at least 256"
msgstr "Stack grootte moet op zijn minst 256 zijn"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr ""
@ -2368,7 +2377,7 @@ msgstr "Niet in staat buffers voor gesigneerde conversie te alloceren"
msgid "Unable to create lock"
msgstr "Kan vergrendeling niet maken"
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr "Geen I2C beeldscherm gevonden bij %x"
@ -3982,12 +3991,14 @@ msgstr "pow() met 3 argumenten vereist integers"
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -4002,6 +4013,7 @@ msgstr "pow() met 3 argumenten vereist integers"
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4496,6 +4508,7 @@ msgstr "watchdog time-out moet groter zijn dan 0"
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr "breedte moet groter dan nul zijn"

View File

@ -581,6 +581,7 @@ msgstr "Obie nóżki muszą wspierać przerwania sprzętowe"
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr "Jasność musi wynosić 0-1,0"
@ -1232,6 +1233,10 @@ msgstr "Niewystarczające uwierzytelnienie"
msgid "Insufficient encryption"
msgstr "Niewystarczające szyfrowanie"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr ""
@ -1468,6 +1473,10 @@ msgstr "Niepoprawna długość słowa/bitu"
msgid "Key must be 16, 24, or 32 bytes long"
msgstr "Klucz musi mieć długość 16, 24 lub 32 bajtów"
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr ""
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr "Lewa strona argumentu nazwanego musi być nazwą"
@ -2092,6 +2101,10 @@ msgstr "Częstotliwość próbkowania musi być dodatnia"
msgid "Sample rate too high. It must be less than %d"
msgstr "Zbyt wysoka częstotliwość próbkowania. Musi być mniejsza niż %d"
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr ""
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr "Skanuj już w toku. Zatrzymaj za pomocą stop_scan."
@ -2153,10 +2166,6 @@ msgstr "Podział z podgrupami"
msgid "Stack size must be at least 256"
msgstr "Stos musi mieć co najmniej 256 bajtów"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr ""
@ -2353,7 +2362,7 @@ msgstr "Nie udała się alokacja buforów do konwersji ze znakiem"
msgid "Unable to create lock"
msgstr ""
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr ""
@ -3954,12 +3963,14 @@ msgstr "trzyargumentowe pow() wymaga liczb całkowitych"
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -3974,6 +3985,7 @@ msgstr "trzyargumentowe pow() wymaga liczb całkowitych"
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4467,6 +4479,7 @@ msgstr ""
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr "szerokość musi być większa niż zero"

View File

@ -6,7 +6,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-04 12:55-0600\n"
"PO-Revision-Date: 2021-11-17 18:26+0000\n"
"PO-Revision-Date: 2021-11-24 23:51+0000\n"
"Last-Translator: Wellington Terumi Uemura <wellingtonuemura@gmail.com>\n"
"Language-Team: \n"
"Language: pt_BR\n"
@ -14,7 +14,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 4.9.1-dev\n"
"X-Generator: Weblate 4.10-dev\n"
#: main.c
msgid ""
@ -594,6 +594,7 @@ msgstr "Ambos os pinos devem suportar interrupções de hardware"
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr "O brilho deve ser 0-1,0"
@ -1258,6 +1259,10 @@ msgstr "Autenticação insuficiente"
msgid "Insufficient encryption"
msgstr "Criptografia insuficiente"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr "A interface deve ser iniciada"
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr "O buffer interno de áudio é muito pequeno"
@ -1494,6 +1499,10 @@ msgstr "O comprimento do bit/palavra são inválidos"
msgid "Key must be 16, 24, or 32 bytes long"
msgstr "A chave deve ter 16, 24 ou 32 bytes de comprimento"
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr "Os mapeamentos do led devem corresponder ao tamanho do display"
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr "O LHS da palavra-chave arg deve ser um ID"
@ -2137,6 +2146,10 @@ msgstr "A taxa de amostragem deve ser positiva"
msgid "Sample rate too high. It must be less than %d"
msgstr "Taxa de amostragem muito alta. Deve ser menor que %d"
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr "As dimensões da escala devem ser poder ser divididas por 3"
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr "O escaneamento já está em andamento. Interrompa com stop_scan."
@ -2199,10 +2212,6 @@ msgstr "Divisão com sub-capturas"
msgid "Stack size must be at least 256"
msgstr "O tamanho da pilha deve ser pelo menos 256"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr "O estéreo à esquerda deve estar no canal PWM A"
@ -2413,7 +2422,7 @@ msgstr "Não é possível alocar buffers para conversão assinada"
msgid "Unable to create lock"
msgstr "Não é possível criar um lock"
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr "Não foi possível encontrar a tela I2C no %x"
@ -4045,12 +4054,14 @@ msgstr "o pow() com 3 argumentos requer números inteiros"
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -4065,6 +4076,7 @@ msgstr "o pow() com 3 argumentos requer números inteiros"
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4559,6 +4571,7 @@ msgstr "o tempo limite do watchdog deve ser maior que 0"
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr "a largura deve ser entre 2 a 8 (inclusive), não %d"
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr "a largura deve ser maior que zero"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2021-11-17 18:26+0000\n"
"PO-Revision-Date: 2021-12-04 12:51+0000\n"
"Last-Translator: Clay <code.clayt@gmail.com>\n"
"Language-Team: none\n"
"Language: ru\n"
@ -16,7 +16,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 4.9.1-dev\n"
"X-Generator: Weblate 4.10-dev\n"
#: main.c
msgid ""
@ -74,16 +74,17 @@ msgstr "%%c требует int или char"
#, c-format
msgid ""
"%d address pins, %d rgb pins and %d tiles indicate a height of %d, not %d"
msgstr ""
"%d адресные выводы, %d rgb выводы и %d плитки указывают высоту %d а не %d"
msgstr "%d адресные пины, %d rgb пины и %d плитки указывают высоту %d а не %d"
#: shared-bindings/microcontroller/Pin.c
#, fuzzy
msgid "%q and %q contain duplicate pins"
msgstr "%q и %q содержат повторяющиеся выводы"
msgstr "%q и %q содержат пины-дупликаты"
#: shared-bindings/microcontroller/Pin.c
#, fuzzy
msgid "%q contains duplicate pins"
msgstr "%q содержит повторяющиеся выводы"
msgstr "%q содержит пины-дупликаты"
#: ports/atmel-samd/common-hal/sdioio/SDCard.c
msgid "%q failure: %d"
@ -170,7 +171,7 @@ msgstr "%q вне диапазона"
#: ports/atmel-samd/common-hal/microcontroller/Pin.c
msgid "%q pin invalid"
msgstr "Вывод %q не допустим"
msgstr "Пин %q не допустим"
#: shared-bindings/fontio/BuiltinFont.c
msgid "%q should be an int"
@ -434,7 +435,7 @@ msgstr "Все каналы событий синхронизации уже и
#: shared-bindings/pwmio/PWMOut.c
msgid "All timers for this pin are in use"
msgstr "Все таймеры для этого вывода уже используются"
msgstr "Все таймеры для этого Пина уже используются"
#: ports/atmel-samd/common-hal/_pew/PewPew.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
@ -472,7 +473,7 @@ msgstr "Поиск сетей wifi уже происходит"
#: ports/cxd56/common-hal/analogio/AnalogIn.c
msgid "AnalogIn not supported on given pin"
msgstr "AnalogIn не поддерживается на данном выводе"
msgstr "AnalogIn не поддерживается на данном пине"
#: ports/cxd56/common-hal/analogio/AnalogOut.c
#: ports/mimxrt10xx/common-hal/analogio/AnalogOut.c
@ -487,7 +488,7 @@ msgstr "AnalogOut имеет только 16 бит. Значение должн
#: ports/atmel-samd/common-hal/analogio/AnalogOut.c
msgid "AnalogOut not supported on given pin"
msgstr "AnalogOut не поддерживается на данном выводе"
msgstr "AnalogOut не поддерживается на данном пине"
#: ports/stm/common-hal/audiopwmio/PWMAudioOut.c
msgid "Another PWMAudioOut is already active"
@ -556,8 +557,7 @@ msgstr "Ниже минимальной частоты кадров"
#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c
msgid "Bit clock and word select must be sequential pins"
msgstr ""
"Битовый тактовый генератор и выбор слова должны быть последовательными "
"выводами"
"Битовый тактовый генератор и выбор слова должны быть последовательными пинами"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
msgid "Bit clock and word select must share a clock unit"
@ -588,10 +588,11 @@ msgstr "Для управления потоком требуется как RX,
#: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c
msgid "Both pins must support hardware interrupts"
msgstr "Оба вывода должны поддерживать аппаратные прерывания"
msgstr "Оба пина должны поддерживать аппаратные прерывания"
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr "Яркость должна быть в диапазоне от 0 до 1.0"
@ -662,7 +663,7 @@ msgstr "Буферы должны быть одинакового размера
#: ports/raspberrypi/common-hal/paralleldisplay/ParallelBus.c
#, c-format
msgid "Bus pin %d is already in use"
msgstr "Вывод шины %d уже используется"
msgstr "Пин шины %d уже используется"
#: shared-bindings/_bleio/UUID.c
msgid "Byte buffer must be 16 bytes."
@ -686,7 +687,7 @@ msgstr "Вызовите super().__init__() перед обращением к
#: ports/espressif/common-hal/alarm/pin/PinAlarm.c
msgid "Can only alarm on RTC IO from deep sleep."
msgstr "Сигнал из глубокого сна может подаваться только на выводе RTC IO."
msgstr "Сигнал из глубокого сна может подаваться только на пине RTC IO."
#: ports/espressif/common-hal/alarm/pin/PinAlarm.c
msgid "Can only alarm on one low pin while others alarm high from deep sleep."
@ -963,8 +964,9 @@ msgid "Display rotation must be in 90 degree increments"
msgstr "Поворот дисплея должен осуществляться с шагом 90 градусов"
#: shared-bindings/digitalio/DigitalInOut.c
#, fuzzy
msgid "Drive mode not used when direction is input."
msgstr ""
msgstr "Drive mode не используется, когда направление является входным."
#: shared-bindings/aesio/aes.c
msgid "ECB only operates on 16 bytes at a time"
@ -1262,6 +1264,11 @@ msgstr "Неполная аутентификация"
msgid "Insufficient encryption"
msgstr "Недостаточное шифрование"
#: ports/espressif/common-hal/wifi/Radio.c
#, fuzzy
msgid "Interface must be started"
msgstr "Интерфейс должен быть запущен"
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr "Внутренний звуковой буфер слишком мал"
@ -1498,9 +1505,13 @@ msgstr "Недопустимая длина слова/бита"
msgid "Key must be 16, 24, or 32 bytes long"
msgstr "Ключ должен быть длинной 16, 24 или 32 байта"
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr ""
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr ""
msgstr "LHS ключевого слова arg должен быть идентификатором(id)"
#: shared-module/displayio/Group.c
msgid "Layer already in a group."
@ -1548,77 +1559,79 @@ msgstr "Отсутствует first_in_pin. Инструкция %d читае
#, c-format
msgid "Missing first_in_pin. Instruction %d shifts in from pin(s)"
msgstr ""
"Отсутствует first_out_pin. Инструкция %d вводит (shifts out) на вывод(ы)"
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
#, c-format
#, fuzzy, c-format
msgid "Missing first_in_pin. Instruction %d waits based on pin"
msgstr ""
msgstr "Отсутствует first_in_pin. Инструкция %d ожидает на основе вывода"
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
#, c-format
msgid "Missing first_out_pin. Instruction %d shifts out to pin(s)"
msgstr ""
"Отсутствует first_out_pin. Инструкция %d выводит (shifts out) на вывод(ы)"
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
#, c-format
#, fuzzy, c-format
msgid "Missing first_out_pin. Instruction %d writes pin(s)"
msgstr ""
msgstr "Отсутствует first_out_pin. Инструкция %d записывает вывод(ы)"
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
#, c-format
msgid "Missing first_set_pin. Instruction %d sets pin(s)"
msgstr ""
msgstr "Отсутствует first_set_pin. Инструкция %d устанавливает вывод(ы)"
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
#, c-format
msgid "Missing jmp_pin. Instruction %d jumps on pin"
msgstr ""
msgstr "Отсутствует jmp_pin. Инструкция %d перепрыгивает на вывод"
#: shared-module/usb_hid/Device.c
#, c-format
msgid "More than %d report ids not supported"
msgstr ""
msgstr "Не поддерживается более %d идентификаторов отчетов (report ids)"
#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c
msgid "Must be a %q subclass."
msgstr ""
msgstr "Должен быть субклассом %q."
#: ports/mimxrt10xx/common-hal/busio/SPI.c shared-bindings/busio/SPI.c
msgid "Must provide MISO or MOSI pin"
msgstr ""
msgstr "Вывод MISO или MOSI должен быть предоставлен"
#: shared-bindings/rgbmatrix/RGBMatrix.c
#, c-format
msgid "Must use a multiple of 6 rgb pins, not %d"
msgstr ""
msgstr "Количество используемых rgb-контактов должно быть кратно 6, а не %d."
#: supervisor/shared/safe_mode.c
msgid "NLR jump failed. Likely memory corruption."
msgstr ""
msgstr "Не удалось выполнить NLR jump. Вероятно, повреждение памяти."
#: ports/espressif/common-hal/nvm/ByteArray.c
msgid "NVS Error"
msgstr ""
msgstr "Ошибка NVS"
#: py/qstr.c
msgid "Name too long"
msgstr ""
msgstr "Имя слишком длинное"
#: ports/nrf/common-hal/_bleio/Characteristic.c
msgid "No CCCD for this Characteristic"
msgstr ""
msgstr "Нет CCCD для этой Characteristic"
#: ports/atmel-samd/common-hal/analogio/AnalogOut.c
#: ports/stm/common-hal/analogio/AnalogOut.c
msgid "No DAC on chip"
msgstr ""
msgstr "ЦАП отсутствует на чипе"
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA channel found"
msgstr ""
msgstr "Канал DMA не найден"
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "No DMA pacing timer found"
@ -1627,31 +1640,31 @@ msgstr ""
#: shared-module/adafruit_bus_device/I2CDevice.c
#, c-format
msgid "No I2C device at address: %x"
msgstr ""
msgstr "Нет устройства I2C по адресу: %x"
#: ports/espressif/common-hal/busio/SPI.c
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/SPI.c
msgid "No MISO Pin"
msgstr ""
msgstr "Нет вывода MISO"
#: ports/espressif/common-hal/busio/SPI.c
#: ports/mimxrt10xx/common-hal/busio/SPI.c ports/stm/common-hal/busio/SPI.c
msgid "No MOSI Pin"
msgstr ""
msgstr "Нет вывода MOSI"
#: ports/atmel-samd/common-hal/busio/UART.c
#: ports/espressif/common-hal/busio/UART.c
#: ports/mimxrt10xx/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c
#: ports/raspberrypi/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c
msgid "No RX pin"
msgstr ""
msgstr "Нет вывода RX"
#: ports/atmel-samd/common-hal/busio/UART.c
#: ports/espressif/common-hal/busio/UART.c
#: ports/mimxrt10xx/common-hal/busio/UART.c ports/nrf/common-hal/busio/UART.c
#: ports/raspberrypi/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c
msgid "No TX pin"
msgstr ""
msgstr "Нет вывода TX"
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
msgid "No available clocks"
@ -1659,85 +1672,87 @@ msgstr ""
#: ports/espressif/common-hal/imagecapture/ParallelImageCapture.c
msgid "No capture in progress"
msgstr ""
msgstr "Захват не ведется"
#: shared-bindings/_bleio/PacketBuffer.c
msgid "No connection: length cannot be determined"
msgstr ""
msgstr "Нет соединения: длина не может быть определена"
#: shared-bindings/board/__init__.c
msgid "No default %q bus"
msgstr ""
msgstr "Нет шины %q по умолчанию"
#: ports/atmel-samd/common-hal/touchio/TouchIn.c
msgid "No free GCLKs"
msgstr ""
msgstr "Свободные GCLK отсутствуют"
#: shared-bindings/os/__init__.c
msgid "No hardware random available"
msgstr ""
msgstr "Отсутствует аппаратный генератор случайных чисел"
#: ports/atmel-samd/common-hal/ps2io/Ps2.c
msgid "No hardware support on clk pin"
msgstr ""
msgstr "Отсутствует аппаратная поддержка вывода clk"
#: ports/atmel-samd/common-hal/alarm/pin/PinAlarm.c
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
msgstr ""
msgstr "Отсутствует аппаратная поддержка на выводе"
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
msgid "No in in program"
msgstr ""
msgstr "Нет in в программе"
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
msgid "No in or out in program"
msgstr ""
msgstr "В программе отсутствует ввод или вывод"
#: shared-bindings/aesio/aes.c
msgid "No key was specified"
msgstr ""
msgstr "Ключ не был указан"
#: shared-bindings/time/__init__.c
msgid "No long integer support"
msgstr ""
msgstr "Нет поддержки длинных целых чисел (long integer)"
#: shared-module/usb_hid/__init__.c
#, c-format
msgid "No more than %d HID devices allowed"
msgstr ""
msgstr "Допускается не более %d HID устройств"
#: shared-bindings/wifi/Radio.c
msgid "No network with that ssid"
msgstr ""
msgstr "Нет сети с этим ssid"
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
msgid "No out in program"
msgstr ""
msgstr "В программе отсутствует вывод"
#: ports/atmel-samd/common-hal/busio/I2C.c
#: ports/espressif/common-hal/busio/I2C.c
#: ports/mimxrt10xx/common-hal/busio/I2C.c ports/nrf/common-hal/busio/I2C.c
#: ports/raspberrypi/common-hal/busio/I2C.c
#, fuzzy
msgid "No pull up found on SDA or SCL; check your wiring"
msgstr ""
"Подтяжка на выводах SDA или SCL не обнаружена; проверь схему подключения"
#: shared-module/touchio/TouchIn.c
msgid "No pulldown on pin; 1Mohm recommended"
msgstr ""
msgstr "Отсутствует подтяжка к земле на выводе; Рекомендуется 1 Мегаом"
#: py/moduerrno.c
msgid "No space left on device"
msgstr ""
msgstr "На устройстве не осталось свободного места"
#: py/moduerrno.c
msgid "No such file/directory"
msgstr ""
msgstr "Файл/директория не существует"
#: shared-module/rgbmatrix/RGBMatrix.c
msgid "No timer available"
msgstr ""
msgstr "Нет доступного таймера"
#: supervisor/shared/safe_mode.c
msgid "Nordic system firmware failure assertion."
@ -1749,31 +1764,34 @@ msgstr ""
#: shared-bindings/ipaddress/IPv4Address.c shared-bindings/ipaddress/__init__.c
msgid "Not a valid IP string"
msgstr ""
msgstr "Недействительная строка IP"
#: ports/nrf/common-hal/_bleio/__init__.c
#: shared-bindings/_bleio/CharacteristicBuffer.c
msgid "Not connected"
msgstr ""
msgstr "Не подключено"
#: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c
#: shared-bindings/audiopwmio/PWMAudioOut.c
msgid "Not playing"
msgstr ""
msgstr "Не играет"
#: shared-bindings/_bleio/__init__.c
#, fuzzy
msgid "Not settable"
msgstr ""
msgstr "Не устанавливается"
#: ports/espressif/common-hal/paralleldisplay/ParallelBus.c
#, c-format
msgid "Number of data_pins must be 8 or 16, not %d"
msgstr ""
msgstr "Количество data_pins должно быть 8 или 16, а не %d"
#: shared-bindings/util.c
msgid ""
"Object has been deinitialized and can no longer be used. Create a new object."
msgstr ""
"Объект был деинициализирован и больше не может быть использован. Создайте "
"новый объект."
#: ports/nrf/common-hal/busio/UART.c
msgid "Odd parity is not supported"
@ -1781,22 +1799,25 @@ msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c
#: ports/raspberrypi/common-hal/audiobusio/PDMIn.c
#, fuzzy
msgid "Only 8 or 16 bit mono with "
msgstr ""
msgstr "Только 8- или 16-битное моно с "
#: ports/espressif/common-hal/wifi/__init__.c
msgid "Only IPv4 addresses supported"
msgstr ""
msgstr "Поддерживаются только адреса IPv4"
#: ports/espressif/common-hal/socketpool/SocketPool.c
msgid "Only IPv4 sockets supported"
msgstr ""
msgstr "Поддерживаются только сокеты IPv4"
#: shared-module/displayio/OnDiskBitmap.c
#, c-format
#, fuzzy, c-format
msgid ""
"Only Windows format, uncompressed BMP supported: given header size is %d"
msgstr ""
"Поддерживается только формат Windows, несжатый BMP: заданный размер "
"заголовка - %d."
#: shared-bindings/_bleio/Adapter.c
msgid "Only connectable advertisements can be directed"
@ -2124,6 +2145,10 @@ msgstr ""
msgid "Sample rate too high. It must be less than %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr ""
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr ""
@ -2185,10 +2210,6 @@ msgstr ""
msgid "Stack size must be at least 256"
msgstr ""
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr ""
@ -2385,7 +2406,7 @@ msgstr ""
msgid "Unable to create lock"
msgstr ""
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr ""
@ -3984,12 +4005,14 @@ msgstr ""
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -4004,6 +4027,7 @@ msgstr ""
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4496,6 +4520,7 @@ msgstr ""
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr ""
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr ""
@ -4557,8 +4582,9 @@ msgid "zi must be an ndarray"
msgstr ""
#: extmod/ulab/code/scipy/signal/signal.c
#, fuzzy
msgid "zi must be of float type"
msgstr ""
msgstr "zi должно быть типа float"
#: extmod/ulab/code/scipy/signal/signal.c
msgid "zi must be of shape (n_section, 2)"

View File

@ -6,7 +6,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-04 12:55-0600\n"
"PO-Revision-Date: 2021-11-16 13:32+0000\n"
"PO-Revision-Date: 2021-11-25 00:02+0000\n"
"Last-Translator: Jonny Bergdahl <jonny@bergdahl.it>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: sv\n"
@ -14,7 +14,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.9.1-dev\n"
"X-Generator: Weblate 4.10-dev\n"
#: main.c
msgid ""
@ -584,6 +584,7 @@ msgstr "Båda pinnarna måste stödja maskinvaruavbrott"
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr "Ljusstyrkan måste vara mellan 0 och 1,0"
@ -1240,6 +1241,10 @@ msgstr "Otillräcklig autentisering"
msgid "Insufficient encryption"
msgstr "Otillräcklig kryptering"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr "Gränssnittet måste vara startat"
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr "Intern ljudbuffert för liten"
@ -1476,6 +1481,10 @@ msgstr "Ogiltig word-/bitlängd"
msgid "Key must be 16, 24, or 32 bytes long"
msgstr "Nyckeln måste vara 16, 24 eller 32 byte lång"
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr "LED-mappning måste matcha displaystorlek"
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr "LHS av keword arg måste vara ett id"
@ -2113,6 +2122,10 @@ msgstr "Samplingsfrekvensen måste vara positiv"
msgid "Sample rate too high. It must be less than %d"
msgstr "Samplingsfrekvensen är för hög. Den måste vara mindre än %d"
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr "Skaldimension måste vara delbar med 3"
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr "Skanning pågår redan. Avsluta med stop_scan."
@ -2174,10 +2187,6 @@ msgstr "Splitting med sub-captures"
msgid "Stack size must be at least 256"
msgstr "Stackstorleken måste vara minst 256"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr "Vänster stereokanal måste använda PWM kanal A"
@ -2384,7 +2393,7 @@ msgstr "Det går inte att allokera buffert för signerad konvertering"
msgid "Unable to create lock"
msgstr "Kan inte skapa lås"
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr "Det gick inte att hitta I2C-display på %x"
@ -4002,12 +4011,14 @@ msgstr "pow() med 3 argument kräver heltal"
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -4022,6 +4033,7 @@ msgstr "pow() med 3 argument kräver heltal"
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4516,6 +4528,7 @@ msgstr "watchdog timeout måste vara större än 0"
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr "width måste vara mellan 2 och 8, inte %d"
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr "width måste vara större än noll"

View File

@ -591,6 +591,7 @@ msgstr "liǎnggè yǐnjiǎo dōu bìxū zhīchí yìngjiàn zhōngduàn"
#: shared-bindings/displayio/Display.c
#: shared-bindings/framebufferio/FramebufferDisplay.c
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "Brightness must be 0-1.0"
msgstr "Liàngdù bìxū wèi 0-1.0"
@ -1251,6 +1252,10 @@ msgstr "Rènzhèng bùzú"
msgid "Insufficient encryption"
msgstr "Jiāmì bùzú"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c
msgid "Internal audio buffer too small"
msgstr "nèi bù yīn pín huǎn chōng qì tài xiǎo"
@ -1487,6 +1492,10 @@ msgstr "Wúxiào de zì/wèi chángdù"
msgid "Key must be 16, 24, or 32 bytes long"
msgstr "mì yào bì xū wéi 16, 24 huò 32 zì jié cháng"
#: shared-module/is31fl3741/IS31FL3741.c
msgid "LED mappings must match display size"
msgstr ""
#: py/compile.c
msgid "LHS of keyword arg must be an id"
msgstr "Guānjiàn zì arg de LHS bìxū shì id"
@ -2123,6 +2132,10 @@ msgstr "Cǎiyàng lǜ bìxū wèi zhèng shù"
msgid "Sample rate too high. It must be less than %d"
msgstr "Cǎiyàng lǜ tài gāo. Tā bìxū xiǎoyú %d"
#: shared-bindings/is31fl3741/IS31FL3741.c
msgid "Scale dimensions must divide by 3"
msgstr ""
#: ports/nrf/common-hal/_bleio/Adapter.c
msgid "Scan already in progess. Stop with stop_scan."
msgstr "Zhèngzài jìn háng sǎomiáo. Shǐyòng stop_scan tíngzhǐ."
@ -2184,10 +2197,6 @@ msgstr "Yǔ zi bǔhuò fēnliè"
msgid "Stack size must be at least 256"
msgstr "Duīzhàn dàxiǎo bìxū zhìshǎo 256"
#: ports/espressif/common-hal/wifi/Radio.c
msgid "Interface must be started"
msgstr ""
#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c
msgid "Stereo left must be on PWM channel A"
msgstr "lì tǐ shēng zuǒ bì xū shì zài PWM tōng dào A"
@ -2393,7 +2402,7 @@ msgstr "Wúfǎ fēnpèi huǎnchōng qū yòng yú qiānmíng zhuǎnhuàn"
msgid "Unable to create lock"
msgstr "Wúfǎ chuàngjiàn suǒ"
#: shared-module/displayio/I2CDisplay.c
#: shared-module/displayio/I2CDisplay.c shared-module/is31fl3741/IS31FL3741.c
#, c-format
msgid "Unable to find I2C Display at %x"
msgstr "Wúfǎ zài%x zhǎodào I2C xiǎnshìqì"
@ -4009,12 +4018,14 @@ msgstr "pow() yǒu 3 cānshù xūyào zhěngshù"
#: ports/espressif/boards/adafruit_funhouse/mpconfigboard.h
#: ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.h
#: ports/espressif/boards/adafruit_metro_esp32s2/mpconfigboard.h
#: ports/espressif/boards/adafruit_qtpy_esp32s2/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.h
#: ports/espressif/boards/ai_thinker_esp_12k_nodemcu/mpconfigboard.h
#: ports/espressif/boards/artisense_rd00/mpconfigboard.h
#: ports/espressif/boards/atmegazero_esp32s2/mpconfigboard.h
#: ports/espressif/boards/crumpspace_crumps2/mpconfigboard.h
#: ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.h
#: ports/espressif/boards/espressif_esp32s3_devkitc_1/mpconfigboard.h
#: ports/espressif/boards/espressif_hmi_devkit_1/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1.3/mpconfigboard.h
#: ports/espressif/boards/espressif_kaluga_1/mpconfigboard.h
@ -4029,6 +4040,7 @@ msgstr "pow() yǒu 3 cānshù xūyào zhěngshù"
#: ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_mini/mpconfigboard.h
#: ports/espressif/boards/lolin_s2_pico/mpconfigboard.h
#: ports/espressif/boards/microdev_macro_s3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_c3/mpconfigboard.h
#: ports/espressif/boards/microdev_micro_s2/mpconfigboard.h
#: ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.h
@ -4526,6 +4538,7 @@ msgstr "kān mén gǒu chāoshí bìxū dàyú 0"
msgid "width must be from 2 to 8 (inclusive), not %d"
msgstr "kuān dù bì xū cóng 2 dào 8 ( hán ), ér bù shì %d"
#: shared-bindings/is31fl3741/IS31FL3741.c
#: shared-bindings/rgbmatrix/RGBMatrix.c
msgid "width must be greater than zero"
msgstr "kuāndù bìxū dàyú líng"

23
main.c
View File

@ -56,6 +56,7 @@
#include "supervisor/shared/safe_mode.h"
#include "supervisor/shared/stack.h"
#include "supervisor/shared/status_leds.h"
#include "supervisor/shared/tick.h"
#include "supervisor/shared/traceback.h"
#include "supervisor/shared/translate.h"
#include "supervisor/shared/workflow.h"
@ -158,7 +159,7 @@ STATIC void start_mp(supervisor_allocation *heap) {
gc_init(heap->ptr, heap->ptr + get_allocation_length(heap) / 4);
#endif
mp_init();
mp_obj_list_init(mp_sys_path, 0);
mp_obj_list_init((mp_obj_list_t *)mp_sys_path, 0);
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script)
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_));
// Frozen modules are in their own pseudo-dir, e.g., ".frozen".
@ -166,7 +167,7 @@ STATIC void start_mp(supervisor_allocation *heap) {
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_FROZEN_FAKE_DIR_QSTR));
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib));
mp_obj_list_init(mp_sys_argv, 0);
mp_obj_list_init((mp_obj_list_t *)mp_sys_argv, 0);
#if CIRCUITPY_ALARM
// Record which alarm woke us up, if any. An object may be created so the heap must be functional.
@ -537,6 +538,8 @@ STATIC bool run_code_py(safe_mode_t safe_mode) {
common_hal_alarm_pretending_deep_sleep();
} else if (connecting_delay_ticks < 0) {
// Entering deep sleep (may be fake or real.)
status_led_deinit();
deinit_rxtx_leds();
board_deinit();
if (!supervisor_workflow_active()) {
// Enter true deep sleep. When we wake up we'll be back at the
@ -678,7 +681,7 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
FATFS *fs = &vfs->fatfs;
boot_output = NULL;
bool write_boot_output = (common_hal_mcu_processor_get_reset_reason() == RESET_REASON_POWER_ON);
bool write_boot_output = true;
FIL boot_output_file;
if (f_open(fs, &boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_READ) == FR_OK) {
char *file_contents = m_new(char, boot_text.alloc);
@ -797,6 +800,9 @@ int __attribute__((used)) main(void) {
supervisor_bluetooth_init();
#endif
// Start the debug serial
serial_early_init();
// Create a new filesystem only if we're not in a safe mode.
// A power brownout here could make it appear as if there's
// no SPI flash filesystem, and we might erase the existing one.
@ -805,9 +811,6 @@ int __attribute__((used)) main(void) {
// displays init after filesystem, since they could share the flash SPI
board_init();
// Start the debug serial
serial_early_init();
// Reset everything and prep MicroPython to run boot.py.
reset_port();
// Port-independent devices, like CIRCUITPY_BLEIO_HCI.
@ -858,7 +861,11 @@ int __attribute__((used)) main(void) {
serial_write_compressed(translate("soft reboot\n"));
}
first_run = false;
skip_repl = run_code_py(safe_mode);
if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
skip_repl = run_code_py(safe_mode);
} else {
skip_repl = false;
}
} else if (exit_code != 0) {
break;
}
@ -905,7 +912,7 @@ void gc_collect(void) {
// This naively collects all object references from an approximate stack
// range.
gc_collect_root((void **)sp, ((uint32_t)port_stack_get_top() - sp) / sizeof(uint32_t));
gc_collect_root((void **)sp, ((mp_uint_t)port_stack_get_top() - sp) / sizeof(mp_uint_t));
gc_collect_end();
}

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -38,3 +38,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -39,3 +39,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
board_reset_user_neopixels(&pin_PA15, 2);
}
void board_deinit(void) {
}

View File

@ -38,3 +38,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -39,3 +39,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
board_reset_user_neopixels(&pin_PA04, 2);
}
void board_deinit(void) {
}

View File

@ -56,3 +56,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -37,3 +37,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -9,3 +9,5 @@ CHIP_FAMILY = samd21
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
CIRCUITPY_ONEWIREIO = 0

View File

@ -37,3 +37,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -37,3 +37,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -37,3 +37,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -9,3 +9,5 @@ CHIP_FAMILY = samd21
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
CIRCUITPY_ONEWIREIO = 0

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -45,3 +45,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -37,3 +37,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -45,3 +45,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -37,3 +37,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
board_reset_user_neopixels(&pin_PA05, 10);
}
void board_deinit(void) {
}

View File

@ -38,3 +38,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -38,3 +38,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -38,3 +38,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -54,3 +54,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
board_reset_user_neopixels(&pin_PB23, 10);
}
void board_deinit(void) {
}

View File

@ -54,3 +54,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
board_reset_user_neopixels(&pin_PB23, 10);
}
void board_deinit(void) {
}

View File

@ -54,3 +54,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
board_reset_user_neopixels(&pin_PB23, 10);
}
void board_deinit(void) {
}

View File

@ -37,3 +37,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -38,3 +38,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -38,3 +38,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -38,3 +38,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -37,3 +37,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -35,3 +35,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

View File

@ -36,3 +36,6 @@ bool board_requests_safe_mode(void) {
void reset_board(void) {
}
void board_deinit(void) {
}

Some files were not shown because too many files have changed in this diff Show More