Move the asic response handling into its own task

This commit is contained in:
Ben 2023-06-12 20:08:31 -04:00 committed by johnny9
parent bc326499ea
commit af22994402
8 changed files with 143 additions and 86 deletions

View File

@ -38,7 +38,7 @@ void SERIAL_init(void) {
//Install UART driver (we don't need an event queue here)
//tx buffer 0 so the tx time doesn't overlap with the job wait time
// by returning before the job is written
uart_driver_install(UART_NUM_1, BUF_SIZE * 2, 0, 0, NULL, 0);
uart_driver_install(UART_NUM_1, BUF_SIZE * 2, BUF_SIZE * 2, 0, NULL, 0);
}
void SERIAL_set_baud(int baud){

View File

@ -13,6 +13,7 @@ SRCS
"./tasks/stratum_task.c"
"./tasks/create_jobs_task.c"
"./tasks/asic_task.c"
"./tasks/asic_result_task.c"
INCLUDE_DIRS
"."
"tasks"

View File

@ -5,6 +5,7 @@
#include "bm1397.h"
#include "system.h"
#include "stratum_api.h"
#include "asic_task.h"
@ -17,6 +18,7 @@ typedef struct {
bm1397Module BM1397_MODULE;
SystemModule SYSTEM_MODULE;
AsicTaskModule ASIC_TASK_MODULE;
char * extranonce_str;

View File

@ -11,6 +11,7 @@
#include "create_jobs_task.h"
#include "global_state.h"
#include "serial.h"
#include "asic_result_task.h"
static GlobalState GLOBAL_STATE = {
.extranonce_str = NULL,
@ -45,8 +46,9 @@ void app_main(void)
BM1397_init();
xTaskCreate(stratum_task, "stratum admin", 8192, (void*)&GLOBAL_STATE, 15, NULL);
xTaskCreate(stratum_task, "stratum admin", 8192, (void*)&GLOBAL_STATE, 5, NULL);
xTaskCreate(create_jobs_task, "stratum miner", 8192, (void*)&GLOBAL_STATE, 10, NULL);
xTaskCreate(ASIC_task, "asic", 8192, (void*)&GLOBAL_STATE, 10, NULL);
xTaskCreate(ASIC_result_task, "asic result", 8192, (void*)&GLOBAL_STATE, 15, NULL);
}

View File

@ -0,0 +1,105 @@
#include "global_state.h"
#include "work_queue.h"
#include "serial.h"
#include "bm1397.h"
#include <string.h>
#include "esp_log.h"
const char * TAG = "asic_result";
void ASIC_result_task(void * pvParameters)
{
GlobalState *GLOBAL_STATE = (GlobalState*) pvParameters;
uint8_t buf[CHUNK_SIZE];
memset(buf, 0, 1024);
SERIAL_clear_buffer();
uint32_t prev_nonce = 0;
while(1){
//wait for a response, wait time is pretty arbitrary
int received = SERIAL_rx(buf, 9, 60000);
if (received < 0) {
ESP_LOGI(TAG, "Error in serial RX");
continue;
} else if(received == 0){
// Didn't find a solution, restart and try again
continue;
}
if(received != 9 || buf[0] != 0xAA || buf[1] != 0x55){
ESP_LOGI(TAG, "Serial RX invalid %i", received);
ESP_LOG_BUFFER_HEX(TAG, buf, received);
continue;
}
uint8_t nonce_found = 0;
uint32_t first_nonce = 0;
struct nonce_response nonce;
memcpy((void *) &nonce, buf, sizeof(struct nonce_response));
uint8_t rx_job_id = nonce.job_id & 0xfc;
uint8_t rx_midstate_index = nonce.job_id & 0x03;
if (GLOBAL_STATE->valid_jobs[rx_job_id] == 0) {
ESP_LOGI(TAG, "Invalid job nonce found, id=%d", nonce.job_id);
}
// ASIC may return the same nonce multiple times
// or one that was already found
// most of the time it behavies however
if (nonce_found == 0) {
first_nonce = nonce.nonce;
nonce_found = 1;
} else if (nonce.nonce == first_nonce) {
// stop if we've already seen this nonce
break;
}
if (nonce.nonce == prev_nonce) {
continue;
} else {
prev_nonce = nonce.nonce;
}
// check the nonce difficulty
double nonce_diff = test_nonce_value(
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[rx_job_id],
nonce.nonce,
rx_midstate_index
);
ESP_LOGI(TAG, "Nonce difficulty %.2f of %d.", nonce_diff, GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[rx_job_id]->pool_diff);
if (nonce_diff > GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[rx_job_id]->pool_diff)
{
SYSTEM_notify_found_nonce(
&GLOBAL_STATE->SYSTEM_MODULE,
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[rx_job_id]->pool_diff,
nonce_diff,
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[rx_job_id]->target
);
uint32_t rolled_version = GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[rx_job_id]->version;
for (int i = 0; i < rx_midstate_index; i++) {
rolled_version = increment_bitmask(rolled_version, GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[rx_job_id]->version_mask);
}
STRATUM_V1_submit_share(
GLOBAL_STATE->sock,
STRATUM_USER,
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[rx_job_id]->jobid,
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[rx_job_id]->extranonce2,
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[rx_job_id]->ntime,
nonce.nonce,
rolled_version ^ GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[rx_job_id]->version
);
}
}
}

View File

@ -0,0 +1,6 @@
#ifndef ASIC_result_TASK_H_
#define ASIC_result_TASK_H_
void ASIC_result_task(void * pvParameters);
#endif

View File

@ -5,32 +5,30 @@
#include <string.h>
#include "esp_log.h"
#include "driver/i2c.h"
static const char *TAG = "ASIC_task";
// static bm_job ** active_jobs; is required to keep track of the active jobs since the
// ASIC may not return the nonce in the same order as the jobs were sent
// it also may return a previous nonce under some circumstances
// so we keep a list of jobs indexed by the job id
static bm_job ** active_jobs;
void ASIC_task(void * pvParameters)
{
GlobalState *GLOBAL_STATE = (GlobalState*) pvParameters;
uint8_t buf[CHUNK_SIZE];
memset(buf, 0, 1024);
uint8_t id = 0;
active_jobs = malloc(sizeof(bm_job *) * 128);
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs = malloc(sizeof(bm_job *) * 128);
GLOBAL_STATE->valid_jobs = malloc(sizeof(uint8_t) * 128);
for (int i = 0; i < 128; i++) {
active_jobs[i] = NULL;
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[i] = NULL;
GLOBAL_STATE->valid_jobs[i] = 0;
}
uint32_t prev_nonce = 0;
int baud = BM1397_set_max_baud();
SERIAL_set_baud(baud);
@ -38,6 +36,7 @@ void ASIC_task(void * pvParameters)
SYSTEM_notify_mining_started(&GLOBAL_STATE->SYSTEM_MODULE);
ESP_LOGI(TAG, "ASIC Ready!");
while (1) {
bm_job * next_bm_job = (bm_job *) queue_dequeue(&GLOBAL_STATE->ASIC_jobs_queue);
if(next_bm_job->pool_diff != GLOBAL_STATE->stratum_difficulty){
@ -68,89 +67,23 @@ void ASIC_task(void * pvParameters)
memcpy(job.midstate3, next_bm_job->midstate3, 32);
}
if (active_jobs[job.job_id] != NULL) {
free_bm_job(active_jobs[job.job_id]);
if (GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] != NULL) {
free_bm_job(GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id]);
}
active_jobs[job.job_id] = next_bm_job;
GLOBAL_STATE->ASIC_TASK_MODULE.active_jobs[job.job_id] = next_bm_job;
pthread_mutex_lock(&GLOBAL_STATE->valid_jobs_lock);
GLOBAL_STATE-> valid_jobs[job.job_id] = 1;
pthread_mutex_unlock(&GLOBAL_STATE->valid_jobs_lock);
SERIAL_clear_buffer();
BM1397_send_work(&job); //send the job to the ASIC
//wait for a response
int received = SERIAL_rx(buf, 9, BM1397_FULLSCAN_MS);
//Time to execute the above code is ~0.3ms
vTaskDelay((BM1397_FULLSCAN_MS - 0.3 ) / portTICK_RATE_MS);
if (received < 0) {
ESP_LOGI(TAG, "Error in serial RX");
continue;
} else if(received == 0){
// Didn't find a solution, restart and try again
continue;
}
if(received != 9 || buf[0] != 0xAA || buf[1] != 0x55){
ESP_LOGI(TAG, "Serial RX invalid %i", received);
ESP_LOG_BUFFER_HEX(TAG, buf, received);
continue;
}
uint8_t nonce_found = 0;
uint32_t first_nonce = 0;
struct nonce_response nonce;
memcpy((void *) &nonce, buf, sizeof(struct nonce_response));
uint8_t rx_job_id = nonce.job_id & 0xfc;
uint8_t rx_midstate_index = nonce.job_id & 0x03;
if (GLOBAL_STATE->valid_jobs[rx_job_id] == 0) {
ESP_LOGI(TAG, "Invalid job nonce found, id=%d", nonce.job_id);
}
// ASIC may return the same nonce multiple times
// or one that was already found
// most of the time it behavies however
if (nonce_found == 0) {
first_nonce = nonce.nonce;
nonce_found = 1;
} else if (nonce.nonce == first_nonce) {
// stop if we've already seen this nonce
break;
}
if (nonce.nonce == prev_nonce) {
continue;
} else {
prev_nonce = nonce.nonce;
}
// check the nonce difficulty
double nonce_diff = test_nonce_value(active_jobs[rx_job_id], nonce.nonce, rx_midstate_index);
ESP_LOGI(TAG, "Nonce difficulty %.2f of %d.", nonce_diff, active_jobs[rx_job_id]->pool_diff);
if (nonce_diff > active_jobs[rx_job_id]->pool_diff)
{
SYSTEM_notify_found_nonce(&GLOBAL_STATE->SYSTEM_MODULE, active_jobs[rx_job_id]->pool_diff, nonce_diff, next_bm_job->target);
uint32_t rolled_version = active_jobs[rx_job_id]->version;
for (int i = 0; i < rx_midstate_index; i++) {
rolled_version = increment_bitmask(rolled_version, active_jobs[rx_job_id]->version_mask);
}
STRATUM_V1_submit_share(
GLOBAL_STATE->sock,
STRATUM_USER,
active_jobs[rx_job_id]->jobid,
active_jobs[rx_job_id]->extranonce2,
active_jobs[rx_job_id]->ntime,
nonce.nonce,
rolled_version ^ active_jobs[rx_job_id]->version
);
}
}
}

View File

@ -1,6 +1,14 @@
#ifndef ASIC_TASK_H_
#define ASIC_TASK_H_
#include "mining.h"
typedef struct {
// ASIC may not return the nonce in the same order as the jobs were sent
// it also may return a previous nonce under some circumstances
// so we keep a list of jobs indexed by the job id
bm_job ** active_jobs;
} AsicTaskModule;
void ASIC_task(void * pvParameters);
#endif
#endif