<commit_before>/**
 * Copyright (c) 2015 Runtime Inc.
 *
 * 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 <string.h>
#include <assert.h>

#include "mcu/nrf.h"
#include "mcu/nrf51_hal.h"

#include <hal/hal_flash_int.h>

#define NRF51_FLASH_SECTOR_SZ	1024

static int nrf51_flash_read(uint32_t address, void *dst, uint32_t num_bytes);
static int nrf51_flash_write(uint32_t address, const void *src,
  uint32_t num_bytes);
static int nrf51_flash_erase_sector(uint32_t sector_address);
static int nrf51_flash_sector_info(int idx, uint32_t *address, uint32_t *sz);
static int nrf51_flash_init(void);

static const struct hal_flash_funcs nrf51_flash_funcs = {
    .hff_read = nrf51_flash_read,
    .hff_write = nrf51_flash_write,
    .hff_erase_sector = nrf51_flash_erase_sector,
    .hff_sector_info = nrf51_flash_sector_info,
    .hff_init = nrf51_flash_init
};

const struct hal_flash nrf51_flash_dev = {
    .hf_itf = &nrf51_flash_funcs,
    .hf_base_addr = 0x00000000,
    .hf_size = 256 * 1024,	/* XXX read from factory info? */
    .hf_sector_cnt = 256,	/* XXX read from factory info? */
    .hf_align = 1
};

#define NRF51_FLASH_READY() (NRF_NVMC->READY == NVMC_READY_READY_Ready)

static int
nrf51_flash_wait_ready(void)
{
    int i;

    for (i = 0; i < 100000; i++) {
        if (NRF_NVMC->READY == NVMC_READY_READY_Ready) {
            return 0;
        }
    }
    return -1;
}

static int
nrf51_flash_read(uint32_t address, void *dst, uint32_t num_bytes)
{
    memcpy(dst, (void *)address, num_bytes);
    return 0;
}

/*
 * Flash write is done by writing 4 bytes at a time at a word boundary.
 */
static int
nrf51_flash_write(uint32_t address, const void *src, uint32_t num_bytes)
{
    int sr;
    int rc = -1;
    uint32_t val;
    int cnt;
    uint32_t tmp;

    if (nrf51_flash_wait_ready()) {
        return -1;
    }
    __HAL_DISABLE_INTERRUPTS(sr);
    NRF_NVMC->CONFIG |= NVMC_CONFIG_WEN_Wen; /* Enable erase OP */
    tmp = address & 0x3;
    if (tmp) {
        if (nrf51_flash_wait_ready()) {
            goto out;
        }
        /*
         * Starts at a non-word boundary. Read 4 bytes which were there
         * before, update with new data, and write back.
         */
        val = *(uint32_t *)(address & ~0x3);
        cnt = 4 - tmp;
        if (cnt > num_bytes) {
            cnt = num_bytes;
        }
        memcpy((uint8_t *)&val + tmp, src, cnt);
        *(uint32_t *)(address & ~0x3) = val;
        address += cnt;
        num_bytes -= cnt;
        src += cnt;
    }

    while (num_bytes >= sizeof(uint32_t)) {
        /*
         * Write data 4 bytes at a time.
         */
        if (nrf51_flash_wait_ready()) {
            goto out;
        }
        *(uint32_t *)address = *(uint32_t *)src;
        address += sizeof(uint32_t);
        src += sizeof(uint32_t);
        num_bytes -= sizeof(uint32_t);
    }
    if (num_bytes) {
        /*
         * Deal with the trailing bytes.
         */
        val = *(uint32_t *)address;
        memcpy(&val, src, num_bytes);
        if (nrf51_flash_wait_ready()) {
            goto out;
        }
        *(uint32_t *)address = val;
    }
    rc = 0;
    if (nrf51_flash_wait_ready()) {<commit_msg>Cortex-M0 does not like unaligned memory accesses.<commit_after>/**
 * Copyright (c) 2015 Runtime Inc.
 *
 * 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 <string.h>
#include <assert.h>

#include "mcu/nrf.h"
#include "mcu/nrf51_hal.h"

#include <hal/hal_flash_int.h>

#define NRF51_FLASH_SECTOR_SZ	1024

static int nrf51_flash_read(uint32_t address, void *dst, uint32_t num_bytes);
static int nrf51_flash_write(uint32_t address, const void *src,
  uint32_t num_bytes);
static int nrf51_flash_erase_sector(uint32_t sector_address);
static int nrf51_flash_sector_info(int idx, uint32_t *address, uint32_t *sz);
static int nrf51_flash_init(void);

static const struct hal_flash_funcs nrf51_flash_funcs = {
    .hff_read = nrf51_flash_read,
    .hff_write = nrf51_flash_write,
    .hff_erase_sector = nrf51_flash_erase_sector,
    .hff_sector_info = nrf51_flash_sector_info,
    .hff_init = nrf51_flash_init
};

const struct hal_flash nrf51_flash_dev = {
    .hf_itf = &nrf51_flash_funcs,
    .hf_base_addr = 0x00000000,
    .hf_size = 256 * 1024,	/* XXX read from factory info? */
    .hf_sector_cnt = 256,	/* XXX read from factory info? */
    .hf_align = 1
};

#define NRF51_FLASH_READY() (NRF_NVMC->READY == NVMC_READY_READY_Ready)

static int
nrf51_flash_wait_ready(void)
{
    int i;

    for (i = 0; i < 100000; i++) {
        if (NRF_NVMC->READY == NVMC_READY_READY_Ready) {
            return 0;
        }
    }
    return -1;
}

static int
nrf51_flash_read(uint32_t address, void *dst, uint32_t num_bytes)
{
    memcpy(dst, (void *)address, num_bytes);
    return 0;
}

/*
 * Flash write is done by writing 4 bytes at a time at a word boundary.
 */
static int
nrf51_flash_write(uint32_t address, const void *src, uint32_t num_bytes)
{
    int sr;
    int rc = -1;
    uint32_t val;
    int cnt;
    uint32_t tmp;

    if (nrf51_flash_wait_ready()) {
        return -1;
    }
    __HAL_DISABLE_INTERRUPTS(sr);
    NRF_NVMC->CONFIG |= NVMC_CONFIG_WEN_Wen; /* Enable erase OP */
    tmp = address & 0x3;
    if (tmp) {
        if (nrf51_flash_wait_ready()) {
            goto out;
        }
        /*
         * Starts at a non-word boundary. Read 4 bytes which were there
         * before, update with new data, and write back.
         */
        val = *(uint32_t *)(address & ~0x3);
        cnt = 4 - tmp;
        if (cnt > num_bytes) {
            cnt = num_bytes;
        }
        memcpy((uint8_t *)&val + tmp, src, cnt);
        *(uint32_t *)(address & ~0x3) = val;
        address += cnt;
        num_bytes -= cnt;
        src += cnt;
    }

    while (num_bytes >= sizeof(uint32_t)) {
        /*
         * Write data 4 bytes at a time.
         */
        if (nrf51_flash_wait_ready()) {
            goto out;
        }
        memcpy(&val, src, sizeof(uint32_t));
        *(uint32_t *)address = val;
        address += sizeof(uint32_t);
        src += sizeof(uint32_t);
        num_bytes -= sizeof(uint32_t);
    }
    if (num_bytes) {
        /*
         * Deal with the trailing bytes.
         */
        val = *(uint32_t *)address;
        memcpy(&val, src, num_bytes);
        if (nrf51_flash_wait_ready()) {
            goto out;
        }
        *(uint32_t *)address = val;
    }
    rc = 0;
    if (nrf51_flash_wait_ready()) {
{'fraction_non_alphanumeric': 0.10710938545990092, 'fraction_numerical': 0.04029990627928772, 'mean_word_length': 2.575873623743418, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3938178', 'n_tokens_mistral': 2813, 'n_tokens_neox': 2625, 'n_words': 714}